Changelog¶
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[Unreleased]¶
Changed¶
- Replaced the user-facing
system_objects_filteredReportWarningincollect_change_report()with a structuredDEBUG-level log entry viaarlogi(src/arodonata/reports/collector.py,openspec/specs/change-reports/spec.md) so routine filtering of background Check Point"System"maintenance objects does not clutter rendered HTML/Markdown evidence reports.
v2.2.0 (2026-10-31)¶
Feat¶
- reports: synthesize snapshot field diffs and style HTML evidence like SmartConsole (#58)
Added¶
- Snapshot-based
FieldDiffsynthesis, pre-change bare-UID resolution,"System"maintenance noise filtering, and SmartConsole-styled inline diff rendering (arodonata.reports,arodonata.mcp.tools):collect_change_report()now synthesizesFieldDiffentries (old_value,new_value,added_items,removed_items) directly fromold-objectandnew-objectsnapshots whenever explicitfield-changesare absent or partial (avoiding false-positive rule diffs when an unchanged referenced group has internal member edits), recursively harvests{uid, name}dictionaries acrossold-objectandnew-objectand resolves bare UUIDs appearing only inold-objectortrack(such as removedgroup.membersortrack.type) viaCachePortand boundedshow-objectlookups, populates structuredObjectChangeEntry.summary_fieldsand enrichedObjectChangeEntry.summary(ipv6-address,subnet4/mask-length4,subnet6/mask-length6,address-rangebounds,members,comments), and excludes non-deleted background Check Point"System"maintenance non-rule objects by default (RenderOptions.include_system_objects: bool = False, also exposed on thechange_reportMCP tool) while emitting asystem_objects_filteredReportWarning(details={"filtered_count": ...}) and preservingChangeReport.raw_responses;apply_session_rule_placement()groups rules by(package, rulebase_type, layer)before sorting in ascending SmartConsole order; andrender_change_report()renders SmartConsole-styled HTML tables (dark-blue#253245headers, full-width pale-yellow#eee8aaaccess section banner rows▾ <section_name> (<section_range>), shadedNo.column,Trackcolumn in both HTML and Markdown, andAccept/Dropaction indicators) with inline cell-level removed/added/before-after diffs (including compositesubnet4=net/maskandrange=first-lastdiffs) in both HTML and Markdown.
v2.1.1 (2026-10-30)¶
Fix¶
- reports: support post-publish OwnedSession placement, cold-cache fallback, and cross-domain lookups (#56)
Security¶
- Explicit
server_iptrust validation and MCP staged-session boundary hardening (arodonata.adapters.checkpoint.sessions,arodonata.cpcrud.executor,arodonata.mcp.tools):LoginCoordinator.resolve_target_ips()andLoginCoordinator.create_dedicated_session()now verify that any caller-suppliedserver_ipbelongs to the configured management host or cachedDomainInfoIPs (active_ip,active_mds_ip,standby_ips,servers) before opening a socket, raisingValidationErroron untrusted destinations; and MCPcpcrud_staged_sessionresolves target domain endpoints internally rather than accepting an unverifiedserver_ipargument.
Fixed¶
- Post-publish
OwnedSessionlive rulebase numbering, object-only session placement short-circuit, cold-cache live published rulebase fallback, and barelayer_uidresolution (arodonata.reports):apply_session_rule_placement()now accepts a clean post-publishOwnedSession(state == "published"orpublished_at is not Nonewithchanges == 0,locks == 0,number-of-published-changes == 0, and matching domain) to read the published rulebase live viasidwithout emittingowned_session_not_usedand best-effort warmCachePort.replace_domain_rulebase()alongsidearodonata_domain_sync_state(numbering_source = "live_published",numbering_basis = "Numbering read live after publish at <time> UTC"derived fromsession_report.publish_time, skipping cache overwrite if a concurrent refresh advancedarodonata_domain_sync_state); short-circuits immediately whensession_report.rule_changesis empty (numbering_source = "not_applicable",numbering_basis = "") while omitting.basis-bannerand- **Numbering Basis**:in HTML and Markdown renderers; falls back to a single-fetch read-onlycollect_domain_rulebase_snapshot()+ cache warm when the local SQL rulebase cache is cold (numbering_source = "live_published",numbering_basis = "Numbering read live from published rulebase at <time> UTC"); and resolves bare UUIDlayerreferences on rule changes via cache and boundedshow-objectlookups into top-levelRuleChangeEntry.layer_name. - Cross-domain cache-first
domain=Nonelookups and ambiguity detection (arodonata.core.errors,arodonata.client,arodonata.core.services.search_service,arodonata.mcp.tools):ArodonataClient.find_object(),SearchService.get_group_members(), and MCPshow_object/get_group_membersnow enforcecache_mode="cache"andinclude_global=Truewhendomainis omitted (preventing multi-domain network refresh storms), reject blank/whitespace targets withValidationError, raiseAmbiguousObjectErrorin the Python SDK when multiple domains match, and returnmatch_type="ambiguous"with candidate objects in MCP tools. LoginGateinter-login spacing without distributed lock starvation, post-revert read-only session recovery, and CPCRUD staged session takeover cleanup (arodonata.adapters.checkpoint.rate_limiter,arodonata.adapters.checkpoint.sessions,arodonata.adapters.checkpoint.client,arodonata.cpcrud.executor):LoginGate.acquire()now releases the cross-processlogin_gate:{mds_ip}distributed lock immediately after recordingmark_login_attemptand sleepslogin_attempt_spacingoutside the distributed lock;is_session_expired_result()classifiesshow-session(withoutuid) returninggeneric_err_object_not_foundafterrevert-to-revisionas an expired session soAMgmtClient.api_call()automatically evicts the wiped SID and re-authenticates; andExecutor._adopt_staged_session()passes{"uid": session_uid, "disconnect-active-session": True}totake-over-sessionwith fallback toswitch-session({"uid": session_uid}) while logging out the initial dedicated session on exit.
v2.1.0 (2026-10-26)¶
Feat¶
- cache,docs: add human-readable composite IDs and v2 documentation (#53)
Fix¶
- docs: fix pymdownx.snippets syntax across example pages (#54)
Added¶
- Human-readable composite identifiers (
object_id,service_id,asset_id) and dual UID/human-readable topology links (arodonata.core.models,arodonata.adapters.storage,arodonata.core.services,arodonata.client,arodonata.mcp): non-unique indexedobject_id = "{mgmt_name}:{domain_name}:{name}"onCPObject/CPObjectRecord(arodonata_objects),service_id = "{mgmt_name}:{domain_name}:{name}"onCPService/CPServiceRecord(arodonata_services), andasset_id = "{mgmt_name}:{domain_name}:{name}"onAsset/AssetRecord(arodonata_assets) alongside UID primary keysid = "{mgmt_name}:{domain_name}:{uid}";id,object_id, andparent_object_idsonGroupMembershipNodeinSearchResult.memberships;parent_id,parent_asset_id,member_asset_ids, andvirtual_system_asset_idsonAsset/AssetRecordwith cross-domain VSX gateway/cluster to Virtual System reconciliation across domains on the same management server; and composite identifier support acrossfind_object(),get_group_members(),search_objects(),query_objects(), and MCP tools (show_object,list_assets,get_group_members,query_objects). - Complete MkDocs Material documentation site (
docs/,mkdocs.yml,.github/workflows/docs.yml), portable standalone HTML guide (docs/_html/arodonata-v2-docs.html), and NotebookLM knowledge bundles (docs-notebooklm/01..04.md).
v2.0.0 (2026-10-26)¶
Feat¶
- mcp: consolidate MCP tool surface into cache-aligned catalog (#9)
- sdk: live integration tests (b1..b7), SDK examples (01..12), and host-app integration hardening (#8)
- mcp: implement Streamable-HTTP MCP server, CLI, security guards, and tool surface (Milestone 6) (#7)
- cpcrud: implement declarative Policy-as-Code CPCRUD engine (#6)
- rulebase,reports: implement rulebase introspection, numbering, and change reports (#5)
- sync: implement core sync/search services and ArodonataClient facade (#4)
- checkpoint: implement native aiohttp transport, TLS verification, and session lifecycle (#3)
- core,storage: implement milestone 1 core foundation and sql storage adapters (#2)
Security¶
- Comprehensive security and specification conformance remediation (
audit-remediation-261025acrossarodonata.adapters,arodonata.core,arodonata.cpcrud,arodonata.rulebase, andarodonata.mcp): strict Web API command-name validation (^[a-z0-9]+(-[a-z0-9]+)*$), disabled HTTP redirects (allow_redirects=False) and ambient proxies (trust_env=False), and phase-classifiedTransportError(connectvspost-send) preventing post-write request resends on failover; cross-processfcntl.flocklocking,0600permission enforcement, and IPv6[host]:portkey normalization inTrustStore; full secret anddatabase_urlpassword masking acrossArodonataSettings/ArodonataMCPSettingsand recursive secret/SID redaction across nested collections and exception chains;arodonata_prefix on all 15 SQLModel tables with positive v1 column fingerprint checks (mdm_dmn,mgmt_dmn_key), cross-worker serialized migration locks (pg_advisory_xact_lock/BEGIN IMMEDIATE), atomic single-transaction cache + sync-state commits, dialectON CONFLICTupserts, and owner-verified distributed lock renewal heartbeats; HMAC-SHA256 credential-boundarodonata_sid_cachekeys,LoginGateself-deadlock elimination and inter-login spacing, Arodonata-onlySessionCleanerfiltering (changes == 0andlocks == 0), and strict prohibition of mutating commands on the shared read-onlyarodonata_sid_cachesession; CPCRUD(object_type, operation)command allowlisting, per-planHybridStateReaderisolation, pre-publish head drift re-verification, and report-verifiedinverse()generation; and MCP read-only command allowlisting, HMAC-SHA256 signedcpcrud_planverification incpcrud_apply/cpcrud_inverse,cpcrud_staged_sessiontool, base64-safe 32-char minimum static token parsing with SHA-256hmac.compare_digest, and fail-closedjwtauthentication.
Added¶
- Consolidated cache-aligned MCP tool surface (
arodonata.mcp,arodonata.core.services,arodonata.client): 13 base tools (list_domains,list_objects,list_services,list_assets,show_objectwith 3-tier exact/anchored-wildcard/substring matching across objects, services, assets, and rulebase layers,search_objects,get_group_membersexpanding network groups, service groups, and cluster/VSX child assets,query_objectswithaggregate="list" | "count" | "describe",show_rulebase,locate_rules,change_report,cache_control, andapi_call) plus 5 opt-in CPCRUD tools (cpcrud_validate,cpcrud_plan,cpcrud_apply,cpcrud_inverse,cpcrud_staged_session) and multi-tableArodonataClient.find_object. - Host application integration hardening (
arodonata.adapters.storage,arodonata.core.services,arodonata.cpcrud,arodonata.rulebase):to_naive_utc()helper and uniform naive UTC timestamps (DateTime(timezone=False),tzinfo=None) across all database tables, domain models, and Check Point timestamp parsers;ARODONATA_TABLE_NAMESnamespace isolation andarodonata_assetstable rename (preventing collision with host applicationassetstables and ignoring non-Arodonata tables inSQLModel.metadata); savepoint-wrapped (begin_nested()) multi-worker schema evolution with automaticDROP+CREATErecovery for incompatible legacy v1 cache tables (domains,sid_cache,arodonata_schema_version);exact_match: bool = FalseinSearchService.search_objects(),ArodonataClient.search_objects(), and MCPsearch_objects; staged session finalization (publish_staged_session,stream_publish_staged_session,discard_staged_session) onCPCRUDServiceandArodonataClientviatake-over-session(uid=session_uid); andrule_to_cpcrud_operation()withoutput_format="cpcrud"support infilter_rulebase()for exporting cached rules into schema-valid CPCRUD operations. - Live Check Point MDSM/SMS integration test harness (
tests/integration/,openspec/specs/integration-testing-and-examples/spec.md),./pytest.shtest runner (unit,int-1..int-7,int-fullwith-venabled by default), and 12 progressive runnable SDK examples (examples/01..12,examples/_session_guard.py,examples/crud_example.yaml,examples/README.md,examples/README_CRUD.md): layered lab environment loader (tests/integration/lab_env.pysupportingARODONATA_LAB=<profile>), non-blocking process-widefcntl.flockrun lock (tests/integration/run_lock.py), live API readiness probe (tests/integration/lab_ready.py), crash-safe domain revision snapshot andrevert-to-revisionbaseline recovery (tests/integration/cp_revision.pyandrestore_baseline.py), standalone diagnostic utilities (probe_lab_domains.py,probe_login_throttle.py,lab_build.py), 60 live integration tests across 7 buckets (b1auth/sessions/reads/search/rate-limiting,b2cache build & CPCRUD live operations,b3publish/revert & 70s login throttle recovery,b4cache mode matrix & multi-domain isolation,b5full rebuild/120-rule pagination/rulebase session refresh/publish matrix/change reports,b6bounded soak loop,b7MCP server & tools), top-level re-exports (Asset,CPObject,CPService,DomainInfo,RefreshOutcome,SearchResult),ArodonataClient.cleanup_server_sessions(), andoteloptional dependency group (arodonata[otel]). - Streamable-HTTP MCP server and standalone CLI (
arodonata.mcp,arodonata[mcp],arodonata-mcp):ArodonataMCPSettings(ARODONATA_MCP_*configuration with secret-safe__repr__and standalone startup validation refusingauth_mode="host"or"jwt"and missingpinnedTLS trust material with exit code2),create_mcp_serverandcreate_asgi_app(ArodonataASGIAppfor Starlette/FastAPI embedding),StaticTokenVerifierandMCPBearerAuthMiddleware(constant-timehmac.compare_digestverification acrossARODONATA_MCP_TOKEN_VARSmapping variable names toclient_idin logs andUserContextwithout logging token values),MCPOriginHostGuardMiddleware(DNS rebinding protection returning HTTP421for unlistedHostand HTTP403for unlistedOrigin), pre-logindomainvalidation against the cachedarodonata_domainstable (with single domain-list refresh on miss) andInvalidCredentialsErrortranslation into actionableToolFailuremessages listing known domains, and MCP prompt templates (audit_session_changes,locate_ip_in_policy,plan_declarative_change). - Declarative Policy-as-Code CPCRUD engine (
arodonata.cpcrud) wired intoArodonataClient(client.cpcrud): offline JSON Schema Draft-07 template validator (CPCRUDService.validate/validate_templateovercheckpoint_ops_schema.jsonwith zero network or database calls),HybridStateReader(isolated per-plan state reader serving objects fromarodonata_objectsand services fromarodonata_servicesstrictly whenarodonata_domain_sync_statefor(scope, item_type)matches the planner'sDomainStamplast_published_atandlast_session_uid, with transparent live API fallback and intra-plan virtual state overlay),PlannerandDiffer(pre-lookupDomainStampcapture, two-axis conflict resolutionNameConflictPolicyxIpConflictPolicywithNamingPrefixesauto-naming,Outcome.ERRORandOutcome.SKIPPED_DEPENDENCYon lookup failures instead of falseCREATE, rule identity matching by key or traffic tuple with Check Point NAT"Original"/"Any"sentinel normalization, and cleanup-rule-aware"bottom"placement anchoring{"above": "<cleanup_rule_uid>"}), dedicated-sessionExecutor(applyandstream_applywithOutcome.PLAN_STALEsafeguard, per-domainWriteSession+SessionOverlayupdates,no_publish=True, keep_session=Truestaging withStagedSessionInfo/StagedSessionEventand SID redaction, post-publishinvalidate_domain, andretry_remainingfolding), and compensating rollback generator (CPCRUDService.inverse/build_inverse_template). - Rulebase introspection, SmartConsole hierarchical numbering (
arodonata.rulebase), and auditable session change reports (arodonata.reports) wired intoArodonataClient: section-stitching rulebase pager (fetch_paged_rulebasemerging splitrulebase-sectionheaders across 100-rule pages and recovering empty trailing sections),RulebaseRefreshService(refresh_rulebases/stream_refresh_rulebaseswith dirty-session refusal, full package/NAT/access/HTTPS/threat/inline/Global placeholder traversal, and atomicreplace_domain_rulebasereplacement),CachedRulebaseSource(get_policy_packages,get_package_rulebase,get_layer_rulebase,locate_rules, automatic domain resolution withAmbiguousLayerName, and localfilter_rulebaseevaluation over cached rules/objects/services), and change report pipeline (collect_change_reportwithSessionScope/RangeScopeUTC validation, deduplication,ReportWarningpartial-failure tracking, bounded 200-UIDshow-objectlookup, read-only liveOwnedSessionrule numbering with full SID redaction and cached snapshot fallback, and offlinerender_change_report/build_change_reportfor self-contained HTML, Markdown, and versioned JSON). - Core synchronization, search services (
arodonata.core.services), and unifiedArodonataClientfacade (arodonata.client):DomainServiceandDomainListRefreshTracker(MDSMshow-domainsdiscovery,Globaldomain synthesis,include_globalfiltering, active/standby failover IP re-resolution, and 1-hour TTL),DomainSyncCoordinator(parallel domain traversal peractive_mds_ipatmax(1, concurrent_limit - 1), per-domain distributed locks, dirty-session checks viashow-session,(last_published_at, last_session_uid)staleness comparison inarodonata_domain_sync_state, and probeInvalidCredentialsErrorfailure handling),ObjectService(pairedrefresh_objects/stream_refresh_objects,CacheMode"cache" | "smart" | "smart-fast" | "force","smart-fast"incremental diff viashow-changeswith fallback on> max_incremental_changes, default("host", "network", "address-range", "group", "dns-domain"), and type-scoped replacement),ServiceCacheService(arodonata_serviceswith default("service-tcp", "service-udp", "service-icmp", "service-group")and selective on-demandtypes=[...]),AssetRefreshService(ClusterRelationshipManagerandVSXRelationshipManagervia encapsulatedgeneric-objectqueries),SearchService(search_objectswith IP/CIDR/range/wildcard/UID/name classification and recursive group traversal up tomax_depth,describe_objects,query_objects, andget_cache_status), andArodonataClient(typed getters,WriteSessionoverlay merging,write_session,auth_context,add_object,set_object,delete_object,find_object,get_group_members,start_object_cache_warmup, andinvalidate_domain). - Check Point native
asynciotransport and session adapter (arodonata.adapters.checkpoint):TrustStoreandTrustPolicy(pinned,tofu,lab-memorywith atomic0600tls_known_hosts.jsonpersistence and cross-IP MDS member certificate recognition),ApiTransportoveraiohttp(post-handshake pre-request SHA-256 fingerprint verification, separateconnect_timeout/read_timeoutApiTimeoutErrorphases, no automatic re-send after socket write, andVerifiedConnectionPoolreusing keep-alive sockets up to 10s idle strictly forshow-*commands),TaskWaiter(exponential backoff2s..10spolling undertask_timeouttolerating up to 5 transient poll errors), continuity-verified object pager (pager.pywith±10boundary swap window recovery and single restart on discontinuity), per-MDS-memberRateLimiter(database slot locks + FIFO waiter queue + coalesced keepalive sweeps) andLoginGate(70sthrottle recovery and fast-failInvalidCredentialsError),LoginCoordinator,SessionCleaner, context-boundWriteSession(SessionOverlayupdates, auto-publish/discard), andAMgmtClientimplementingApiPort. - Core foundation (
arodonata.core) and SQL storage adapter (arodonata.adapters.storage):ArodonataSettings, exception hierarchy with SID/secret redaction,@tracedandspan_attrsinstrumentation, typed domain progress events (SyncProgressEvent,CPCRUDEvent),contextvars-boundAuthContext,UserContext, andWriteSessionwithSessionOverlay, Pydantic v2 domain models, hexagonal protocols (ApiPort,CachePort,LockPort,AuthProvider),DatabaseManager(SQLite + PostgreSQL with SHA-256 schema hash auto-migration viaarodonata_schema_version),SqlLockAdapter,SqlCacheAdapter, and SSE boundary adapter (arodonata.adapters.sse).
Changed¶
- Revised all OpenSpec capability specifications for Arodonata v2 clean-slate hexagonal architecture: native
aiohttptransport (replacingcpapi),SqlCacheAdapter(replacingPostgresCacheAdapter/CacheRepository), canonicalCacheModenames (cache,smart,smart-fast,force), paired coroutine andstream_*domain event APIs (removingSSEEventfrom core), and unifiedArodonataClientfacade (replacingarodonata.helpers).
Fixed¶
- Check Point R82 live compatibility and persistent cache/session reuse fixes:
ArodonataClientandAMgmtClientnow honorsettings.database_urlwhenengine=None, auto-create parent directories for file-backed SQLite URLs, preservearodonata_sid_cacheentries onclose()for persistent databases, and skip redundant startupSessionCleanerlogins when a valid system-domain SID is already cached;LoginCoordinatorclassifies generic R82"Authentication to server failed."(err_login_failed) as non-retryableInvalidCredentialsError;DomainSyncCoordinatorandObjectServiceextract"iso-8601"from dict-formattedpublish-timeand unwrap task-basedshow-changesoperationsarrays;Collectorpassesview-published-sessions=Truefor published session discovery; andPlanner._find_existing_nat_ruleresolves inline object/service names to UIDs for idempotent NAT rule re-planning.