# Project persistence Project owns `pharos_project` and its restricted runtime role. Administration applies the shared delivery migrations and the checksummed owner migration before startup. `NewReadRepository` reads canonical state without enabling a source. `New` additionally binds one enrolled provider, instance, source scope and management generation for acquisition workers. ## Intake and acquisition `RequestRefresh` reserves a random canonical Project ID against an exact unique provider tuple. A reservation awaiting its first complete read has no canonical Project or membership authority. Existing reservations retain their scope and management generation; this adaptor has no implicit ownership transfer. `AcceptNotice` compares the source-qualified actual scope with enrolment. An in-scope delivery commits its receipt and requested refresh sequence together. A successfully read foreign scope commits an `ignored` receipt with that scope. Explicit source absence or access denial commits an `unavailable` receipt with `failure='source_not_found'` or `failure='source_access_denied'` respectively and `scope_ref=NULL`. This includes foreign Projects hidden from the reader. Both dispositions retain the provider tuple, enrolled scope and fingerprint, and create no source reservation or authority event. Migration 0007 adds the unavailable disposition while preserving accepted, ignored and quarantined receipts. It permits ACK without Project work; later inventory or a new delivery can independently schedule a complete read. A source delivery ID deduplicates the exact body fingerprint and binding. A different delivery occurrence can request another refresh even when its body is identical. `Quarantine` shares this receipt identity and retains a digest and safe failure category. Changed bytes or a changed accepted/quarantined disposition are rejected. `NoticeRecorded` validates replay before provider I/O; receipt identity includes the provider tuple and original enrolled scope. Transport acknowledgement follows this durable result. Reprocessing a quarantined notice needs an explicit administrative decision. `ClaimRefresh` leases one source for 30 seconds using database time, a random token and a monotonic generation. It records the Project's expected revision. Provider and Party reads take place outside the transaction. The worker retains one complete `PreparedObservation` for record retries; another provider read requires a new claim. `RecordObservation` locks that source and invokes one aggregate transaction. The plain application handler receives a scoped repository and lease admission. Snapshot, optimistic version, command receipt, recorded outcome, private facts, immutable acquisition receipt and successful-read evidence commit together. The source authority revision and exact public authority event bytes commit in that transaction as well, including for a materially unchanged read. Outbox encoding failure rolls back all of them. A stale worker cannot commit, release or delay a newer lease. The completion fence is checked again after staging outgoing facts. ## Material state and source evidence Versioned snapshots contain canonical metadata, the retained exact source, management generation and complete observed memberships. Qualified Party associations remain distinct from unresolved provider members. The snapshot codec rejects missing, duplicate, unknown, null and malformed identity fields before restoring domain authority. A successful unchanged read records a new acquisition and complete-read time while retaining the Project version and material events. Acquisition IDs are unique across retained history. Exact command replay returns its recorded outcome before lease admission and never renews freshness. Provider failures retain the prior snapshot and complete-read time, recording a safe retry category separately. `RetryRefresh` records consecutive failures and uses database time for delays of 5, 10, 20, 40, 80, 160 and 300 seconds. The eighth failure sets `exhausted_at`; subsequent fenced probes retain that timestamp, saturate the counter at eight and continue every five minutes. `last_attempt_at` records each failed acquisition; repeating the same failure category preserves `failed_at`, the authority revision and its event. A changed failure category publishes a new transition. Inventory and notices preserve existing deadlines and failure counts; notices also preserve failed authority once exhausted. Success resets the budget. `RecoverSource` atomically records an immutable operator decision and brings an exhausted source's next probe forward at its expected generation in the enrolled scope. It advances the lease fence and resets the budget while retaining failed authority and all complete-read evidence. Replaying the command cannot resume a later exhaustion. Migration 0006 adds these workflow fields and retains notice identity independently of source reservations, so reviewed administrator cleanup can remove an unobserved misfiled source without erasing its receipt. The [issue #1003 cleanup procedure](../../../../../../docs/operations/project-source-cleanup-1003.md) requires verified source tuples, refuses canonical history and archives affected rows before removing the two invalid reservations. An initial reservation or accepted source notice within the retry budget advances authority to `pending` in the same transaction as its durable intent. Routine refreshes only schedule work. `invalidated_sequence` records the latest notice separately from scheduled work, so an older in-flight read cannot clear a newer notice. Routine scheduling also preserves a previous failure. A first or changed provider failure advances authority to `failed`. Each transition has a dedicated durable outbox and dispatch lease because it can occur before the first Project aggregate exists and does not share the material aggregate revision. The event carries the original transition and complete-read times plus the owner-calculated absolute validity. Delivery retry preserves the event identity and bytes. Reads fetch root and source evidence in one database statement, then verify identity, scope, management generation, material fingerprint and revision. An outstanding invalidating notice makes retained authority `pending`; a failed attempt makes it `failed`. Routine work preserves its current state and expiry. The application query applies its configured freshness budget to otherwise `ready` evidence. Missing or failed provider reads cannot close a Project or clear its memberships. ## Publication and recovery A lifecycle-managed cleanup worker removes confirmed authority dispatches and their payloads after 24 hours from publisher confirmation, in pages of 256. Cleanup uses database time and skips locked rows. Pending, retryable and leased work remains recoverable. The current source evidence, acquisition identities and command receipts remain intact, so old command replay cannot renew or republish cleaned authority. This bounds delivered outbox retention; it does not prune the separate acquisition/command history. Migration 0004 preserves existing pending work as invalidated and grants the Project runtime deletion only on its two authority delivery tables. Reapply broker administration to install the generated authority expiry policy on existing queues; their declarations and bindings stay valid. Older quorum messages retain their original expiry and are drained by consumer bootstrap. Their retained timestamps cannot renew authority. Saving a material root stages owner-private Project facts. The publication subscriber maps those facts to canonical integration events with the same revision and occurrence time. Encoded payloads and their complete envelopes are bounded before persistence. Unresolved member identities remain private. `ListProjectIntegrationSnapshots` creates one 24-hour immutable checkpoint in a repeatable-read transaction. The checkpoint contains the complete canonical snapshot set for an exact provider, instance and source scope. Stable keyset pages cannot race later Project changes. Each item records its canonical UUID, Project revision and SHA-256 hash of the agreed integration snapshot. The checkpoint manifest hashes the ordered item identity, revision and item hash. Closed Projects stay in the checkpoint; migration 0008 lets an item record the `closed` lifecycle, which the original `active`/`retired` check refused. Checkpoint creation commits its marker to a dedicated synchronisation outbox in the same owner transaction. `ReplayPage(ctx, runID, limit)` records a durable administrative cursor and stages private complete-snapshot facts in pages of up to 100 roots. It retains each material revision and its original private fact's occurrence time. It preserves source evidence and emits no access-change reaction. A lost commit response can be retried with the same run ID. The retained original outbox fact supplies provenance; missing or corrupt provenance fails the replay. Consumers must bind before bootstrap and fence revisions while reconciling concurrent events. Run `python3 scripts/go.py run ./services/project-source-replay --run-id UUID` from the repository root, replacing `UUID` with a fresh canonical UUID and supplying the restricted `PROJECT_DATABASE_URL_FILE`. Retry an interrupted run with the same UUID. `--limit` bounds each committed page to 1–256 snapshots. Beto's running publication workers deliver the resulting intents. The durable notice, lease, receipt-replay and resumable replay behaviour adapts the reference producer from [`feat/metallo-waldur-membership-events` at `39e5221cd`](https://github.com/pharos-ai-factory/pharos-platform/tree/39e5221cd8cbb086da3dde89cd33662fbda78fd5/services/metallo/contexts/project_provisioning). Canonical identity, source freshness and ownership remain Project concerns in Beto; this adaptor imports no Metallo or Party implementation. ## Verification `python3 scripts/beto_native_integration.py` creates an isolated native PostgreSQL cluster, applies each context migration twice and runs the foundation, Party and Project integration tests with race detection. Project coverage includes concurrent notice acceptance, uniqueness, immutable scope, quarantine, same-command conflict, lost-response replay, unchanged freshness, member removal, lease recovery, rollback, acquisition-ID reuse, explicit expected versions, pending/failed source status, resumable replay, corrupt snapshots and denied cross-context/administrative access. Authority coverage includes unchanged-read renewal, pending and failed invalidation, exact retry bytes, source expiry and replay that cannot renew validity. Snapshot and event mapping unit tests run with the ordinary Beto suite. Synchronisation coverage includes a late subscriber, changes between pages, immutable old pages, linked pending members, a subsequent changed checkpoint, lost-view reconstruction and durable checkpoint publication.