Assistant: codex Assistant-Model: gpt-6.1-sol Assistant-Session: 01a15374-f59f-7a31-86d2-d23b5d2ed181
161 lines
9.5 KiB
Markdown
161 lines
9.5 KiB
Markdown
# Custodian fleet input publication contract
|
|
|
|
Owner recommendation, 2026-10-19; source preparation only. Repo Manager owns
|
|
commit selection and work-record publication. Activity Core owns scheduling,
|
|
private consumer storage, admission and run evidence. Custodian owns daily report
|
|
semantics. These are proposed defaults, not runtime acceptance or an activation.
|
|
|
|
## Reuse and exact missing boundary
|
|
|
|
`rmgr freshness run --limit N --max-seconds S` already observes Forge default HEAD,
|
|
verifies the primary Hub projection and writes durable
|
|
`repo-manager.freshness-receipt.v1` receipts. It explicitly makes no checkout.
|
|
The classification publisher's snapshots contain metadata, not work-record files.
|
|
Neither command currently supplies a filesystem tree to Custodian commands.
|
|
Do not reinterpret Hub rows or a classification snapshot as those input files.
|
|
|
|
The new offline prerequisite is:
|
|
|
|
```
|
|
python -m repo_manager.fleet_snapshot --request selected-commits.json --output snapshots/<unique-run-id>
|
|
```
|
|
|
|
It reads existing local Git objects, never fetches, checks out, changes a repo,
|
|
contacts Hub/Forge, or reads a credential. This is a module CLI rather than a
|
|
new daemon or scheduler. The publication owner supplies object stores using its
|
|
existing approved Git delivery path. Choosing that runtime source/access path
|
|
is still required; the exporter itself needs no network or authentication.
|
|
|
|
Request contract:
|
|
|
|
```json
|
|
{
|
|
"observed_at": "2026-10-19T07:00:00+02:00",
|
|
"repositories": [
|
|
{"slug": "the-custodian", "path": "/accepted/local/object-store/the-custodian", "commit": "<full-40-character-commit>"}
|
|
]
|
|
}
|
|
```
|
|
|
|
The example commit is a placeholder, deliberately not runnable. The publisher
|
|
must retain each matching Forge observation/receipt ID separately; `observed_at`
|
|
is supplied evidence, not a freshness assertion made by the offline exporter.
|
|
Only `workplans/**/*.md` (including archived dependencies) and `decisions/*.md`
|
|
are copied. Git symlinks, submodules at selected record paths, invalid slugs,
|
|
non-full commit IDs, absent workplans and oversize records are refused. Dirty
|
|
working files, .git, credentials and unrelated files are not copied. Limits are
|
|
2MiB per record and 64MiB total per export; exceeding either is an explicit
|
|
publication failure, never partial accepted coverage.
|
|
|
|
Each new unique output contains `<slug>/workplans`, optional `<slug>/decisions`,
|
|
`manifest.json` and finally `COMPLETE`. Manifest schema
|
|
`repo-manager.fleet-input.v1` records the requested observation time, all commits,
|
|
file byte lengths and SHA-256 values. `freshness_verified: false` is intentional.
|
|
`COMPLETE` contains the manifest SHA-256. Consumers must validate this marker,
|
|
manifest and every file before accepting a publication. Failed promotion leaves
|
|
no COMPLETE and must never be consumed. Names are never overwritten, even empty
|
|
existing directories. The owner protects the output parent against concurrent
|
|
untrusted writers. This is completion-marked publication, not a crash-durable
|
|
transaction or automatically enforced read-only store. Do not change published
|
|
files; mount the selected immutable directory read-only for the consumer.
|
|
|
|
## Recommended default daily policy
|
|
|
|
Initial scope is the existing report estate: the-custodian, net-kingdom,
|
|
railiance-platform, activity-core, access-engine, secrets-engine, ops-mason,
|
|
ops-warden, key-cape, user-engine, tenant-engine, gate-house, kings-guard,
|
|
policy-nexus and rapp-policy-nexus. This is a proposed explicit allowlist, not
|
|
permission to publish every registered repo. The same selected set bounds
|
|
both workplan reporting and decision synchronization. Review additions for
|
|
cross-repo dependency completeness; missing dependencies remain unknown.
|
|
|
|
Recommend one pre-run publication step in the existing native daily workflow,
|
|
not a separate timer. Reuse Repo Manager's Forge HEAD/primary receipt verification
|
|
for the selected set, then export those exact commits from accepted object stores.
|
|
`rmgr freshness run --repos <comma-separated-set> --limit 15 --max-seconds <budget>`
|
|
now targets exactly the approved active set, rejecting missing active repos or a
|
|
limit smaller than the set. The default untargeted mode still rotates fleet
|
|
members. The publisher must inspect deferred/failure results and join successful
|
|
per-repo receipts for every selected repo; command invocation alone is not
|
|
complete coverage. No fabricated receipt or forced reconciliation is acceptable.
|
|
|
|
Recommended admission: observations at most 2 hours old at daily start, no future
|
|
observation beyond 5 minutes of clock tolerance, all required repos present,
|
|
full commits matching the verified observations, exact file hashes, and COMPLETE
|
|
valid. Old commit age is not failure when its HEAD was recently re-observed.
|
|
Never rewrite an old snapshot's timestamp to make it fresh. On missing/stale
|
|
inputs, fail before `security_flow_daily.py --apply`, retain a sanitized missing
|
|
repo/reason receipt and notify through the existing Activity Core failure path.
|
|
Do not silently reuse yesterday's tree. Activity Core now requires the consumer freshness/content gate and supports
|
|
immutable descriptor selection. The remote capture/transfer publication step
|
|
is still unimplemented; neither local source test proves runtime publication.
|
|
|
|
Hold a specific snapshot path throughout a run and its retries. Avoid `current`
|
|
symlinks (executor rejects them) and in-place directory replacement. Placement
|
|
must supply an immutable per-run path or a serialized binding update while
|
|
consumers are quiescent. Activity Core's prepared consumer selects an immutable child directory from a
|
|
regular descriptor carrying manifest/receipt hashes. The receiver must finish
|
|
retaining both artifacts before atomically replacing that descriptor. Transport
|
|
and receiver implementation remain required before activation.
|
|
|
|
## Retention and weekly boundary
|
|
|
|
Recommend retaining 35 days of daily publications plus every snapshot referenced
|
|
by an unresolved failure, checkpoint, audit or accepted recommendation. Capacity
|
|
planning must use measured export sizes, not assume the shared 1Gi claim suffices.
|
|
Pruning is owner-reviewed initially; this exporter performs no deletion. Keep
|
|
manifest/receipt hashes with run evidence and back up private state separately.
|
|
Restore testing and capacity alarms are delivery gates, not established here.
|
|
|
|
Weekly sizing uses the existing cluster, resource-control, telemetry, inventory,
|
|
provenance and optional previous-report/review inputs. Repo Manager must not
|
|
manufacture telemetry or impersonate those collectors. Recommend retaining at
|
|
least 13 weekly bundles plus all referenced/open recommendation evidence, with
|
|
evaluation windows preserved. Custodian owns the weekly request and collector
|
|
coverage validation; Activity Core owns immutable request handoff and retained
|
|
report storage. Daily Git snapshots do not satisfy weekly measurement coverage.
|
|
|
|
## Owner handoff and validation
|
|
|
|
Repo Manager recommendation: use this bounded offline export after the existing
|
|
Forge receipt checks, with the explicit 15-repo set and 2-hour admission default.
|
|
Activity Core should add the manifest/freshness gate and per-run immutable binding
|
|
when implementing the chosen worker placement; never loosen symlink validation.
|
|
No public API, broad clone service, extra schedule or new credential path is
|
|
needed. Production receipt verification, object-store provisioning, consumer gate,
|
|
retention/storage acceptance and first scheduled evidence remain unfinished.
|
|
|
|
Local tests use temporary Git repositories and prove committed-byte export despite
|
|
dirty files, strict path selection, hashes/completion marker, immutable names,
|
|
invalid-request refusal, selected symlink refusal and size bounds. They perform no
|
|
network, production reads, schedule changes or Hub writes.
|
|
|
|
## Wind-down checkpoint: disabled remote capture source
|
|
|
|
`custodian_snapshot.py` and the existing runtime now prepare a fixed-policy
|
|
`POST /ports/repositories/custodian-snapshot` endpoint. Default is404/disabled.
|
|
Configuration requires `REPO_MANAGER_CUSTODIAN_SNAPSHOT_ENABLED=true`,
|
|
`REPO_MANAGER_CUSTODIAN_SNAPSHOT_POLICY` and
|
|
`REPO_MANAGER_CUSTODIAN_SNAPSHOT_HUB`; existing PublisherSettings supplies the
|
|
authorized Forge reader. Existing optional API-token admission is preserved.
|
|
No caller paths/refs/repos/commands are used. No source endpoint is deployed.
|
|
|
|
Capture targets the complete configured set through native freshness, then reads
|
|
allowlisted files at those exact commits through Forge contents API. It verifies
|
|
Git blob identity, refuses unexpected/symlink files and returns a content-
|
|
addressed manifest/receipt/file bundle. Default hard payload bound8MiB and
|
|
per-response bound3MiB fail closed. Publisher state has no new persistent volume.
|
|
|
|
Validation: 47 publisher/capture/freshness/exporter tests passed with mocked HTTP;
|
|
one existing Starlette/httpx deprecation warning. Source lint review remains a
|
|
restart check. The source endpoint uses a process-local concurrency lock and
|
|
240-second native budget; it does NOT cancel producer work on client disconnect
|
|
or retain durable in-progress receipt state. Do not treat it as ready for the
|
|
proposed45-second combined daily pre-run phase. Existing15-repo capture timing
|
|
has not been measured. Activity Core receiver is standalone and unintegrated;
|
|
see its `k8s/custodian-release/RESTART.md` for exact restart steps.
|
|
|
|
The core-hub publisher's existing CCR0031 reader remains in that namespace. New
|
|
Activity Core access to private workplan/decision content and publisher-to-Hub
|
|
egress require the explicit source-reviewed data/network delta before live
|
|
promotion. No credential route, access scope or schedule was changed here.
|