Commit graph

65 commits

Author SHA1 Message Date
94541a29e2 docs(agents): repoint remote State Hub URL to the in-cluster address
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
The remote row pointed at 127.0.0.1:18000, a reverse tunnel back to the
workstation. On railiance01 the State Hub runs in the cluster on that same
machine, so the request left the box and came back to reach a local service.

Refs CUST-WP-0067-T07

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 2583210@bnt-lap001
Assistant-Session: f2bff2d5-e9b2-4338-92ca-10282a927006
2026-08-25 00:20:39 +02:00
6b40e0cd25 Adopt Target Revenue Source License V1C1 (org-wide preliminary rollout)
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
Maintainer decision, 2026-07-29: adopts TRSL V1C1 as this repo's
preliminary governing license, per target-revenue's
workplans/TREV-WP-0008-governance-and-pilot-rollout.md T05. Full
specialist legal review is deferred until out of beta (target-revenue
SCOPE.md §1). No Phase is yet declared for this repo.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-29 23:52:12 +02:00
a71d0d9b96 docs: workplan-first agent guidance prose (CUST-WP-0055 T04)
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 2s
2026-07-08 16:35:47 +02:00
07feabe9cc Regenerate agent instructions from state-hub templates (CUST-WP-0055 T01)
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 3s
Sync AGENTS.md, CLAUDE.md, and .claude/rules from updated project_rules
templates: workplan-first session protocol, legacy terminology footnote,
and GET /workplans/ examples.
2026-07-08 14:50:16 +02:00
ea172b3333 Add Forgejo CI smoke workflow (enablement template)
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 2s
2026-07-08 00:25:57 +02:00
ccce4e8120 Draft capability entry (reuse-surface REUSE-WP-0017-T04, cohort 1)
Honest first-pass maturity vector grounded in README/docs/tests present
in this repo; no invented evidence. Flagged for human review before
publish. See reuse-surface history/2026-07-06-coverage-classification.md.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-06 19:03:42 +02:00
544010880c chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-07-02:
  - update .custodian-brief.md for artifact-store
2026-07-02 11:27:11 +02:00
1a0acf60f9 ARTIFACT-STORE-WP-0007 D7.5 + finish: follow-up routing and MinIO-compatibility decision
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 11:26:45 +02:00
01c88169f4 chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-07-02:
  - update .custodian-brief.md for artifact-store
2026-07-02 11:24:02 +02:00
8fbce69475 ARTIFACT-STORE-WP-0007 D7.4: STS temporary credential support (session token + refreshable file refs)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 11:23:44 +02:00
68a5ff0ba2 chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-07-02:
  - update .custodian-brief.md for artifact-store
2026-07-02 11:16:13 +02:00
f4a7b92543 ARTIFACT-STORE-WP-0007 D7.3: STS credential vending assessment for NetKingdom
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 11:15:45 +02:00
e1dd365586 chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-07-02:
  - update .custodian-brief.md for artifact-store
2026-07-02 11:13:19 +02:00
83ce888e78 ARTIFACT-STORE-WP-0007 D7.2: deterministic local MinIO fixture, live compatibility pass
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 11:13:03 +02:00
8f454da406 Advance MinIO compatibility lane 2026-06-27 23:37:55 +02:00
5858a7309b chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-06-27:
  - update .custodian-brief.md for artifact-store
2026-06-27 23:32:57 +02:00
cdcd2390c4 chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-06-22:
  - update .custodian-brief.md for artifact-store
2026-06-22 23:19:06 +02:00
9561e9620f Normalize agent instructions and workplan frontmatter (STATE-WP-0067)
- Align agent files with on-disk workplan prefixes (infer from workplan ids)
- Set workplan domain to registered domain_slug; add topic_slug where applicable
- Repair frontmatter delimiter formatting; migrate legacy task status literals
- Regenerate AGENTS.md, CLAUDE.md, and .claude/rules from State Hub templates
2026-06-22 23:16:24 +02:00
fca7b7c0e8 Add .repo-classification.yaml (CUST-WP-0050 T11 agent first-pass) 2026-06-22 17:47:34 +02:00
e689929da0 Add credential routing instructions for all agent runtimes
Propagate shared credential-routing section (Codex, Claude, Grok, llm-connect)
from state-hub template via scripts/propagate_credential_routing.py.
2026-06-18 22:48:37 +02:00
0fd2f29e87 Add capability registry scaffold (REUSE-WP-0014-T03 B01)
Empty helix_forge registry layout for federation publishing.
2026-06-16 01:50:12 +02:00
bcda9ad1d7 Refresh agent instruction files 2026-05-18 16:55:40 +02:00
93ca9ea3b9 Add MinIO STS follow-up workstream 2026-05-17 13:45:01 +02:00
4df29ba9f0 chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-17:
  - update .custodian-brief.md for artifact-store
2026-05-17 13:37:34 +02:00
cbbbe93594 chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-17:
  - update .custodian-brief.md for artifact-store
2026-05-17 00:26:54 +02:00
a60d24f814 Add reference-counted garbage collection 2026-05-17 00:26:19 +02:00
1dae855700 chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-17:
  - update .custodian-brief.md for artifact-store
2026-05-17 00:24:54 +02:00
91bb08c8e5 Add guide-board pilot ingestion 2026-05-17 00:09:11 +02:00
1f379ba321 chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-17:
  - update .custodian-brief.md for artifact-store
2026-05-17 00:07:30 +02:00
864f7f203c Add S3 backend and storage verification 2026-05-16 23:26:03 +02:00
b7ceaf7682 chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-16:
  - update .custodian-brief.md for artifact-store
2026-05-16 23:24:37 +02:00
c33baa3635 Implement HTTP ingestion and retention lifecycle 2026-05-16 23:10:21 +02:00
2173f702c1 chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-16:
  - update .custodian-brief.md for artifact-store
2026-05-16 23:07:57 +02:00
b9ae4d83ba chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-16:
  - ARTIFACT-STORE-WP-0003-T001: done → cancelled
2026-05-16 23:07:56 +02:00
788e585694 chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-16:
  - update .custodian-brief.md for artifact-store
2026-05-16 22:41:08 +02:00
5911a7bca0 chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-16:
  - ARTIFACT-STORE-WP-0003-T001: in_progress → cancelled
2026-05-16 22:41:06 +02:00
66a8ce1bc9 chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-16:
  - update .custodian-brief.md for artifact-store
2026-05-16 15:15:20 +02:00
64b1e95104 chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-16:
  - ARTIFACT-STORE-WP-0005-T001: todo → cancelled
2026-05-16 14:46:19 +02:00
5ece71f375 chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-16:
  - ARTIFACT-STORE-WP-0004-T001: todo → cancelled
2026-05-16 14:46:19 +02:00
b8806fd58f chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-16:
  - ARTIFACT-STORE-WP-0003-T001: todo → cancelled
2026-05-16 14:46:18 +02:00
53c03d65a3 chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-16:
  - ARTIFACT-STORE-WP-0002-T001: todo → cancelled
2026-05-16 14:46:18 +02:00
053afc9505 chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-16:
  - update .custodian-brief.md for artifact-store
2026-05-16 09:12:05 +02:00
f90c761ef6 WP-0001-T008: operator docs + ADR cross-linking; mark WP-0001 done
docs/OPERATOR.md (new): runbook with prerequisites, quick start,
environment variables, SQLite + PostgreSQL setup, storage layout,
CLI reference, HTTP /health reference, an end-to-end Python smoke
test (create_package -> ingest_file -> finalize -> manifest), the
replay / disaster-recovery procedure, common failure modes, and a
References section that links every ADR (0001..0006), the
blueprint, platform ambition, roadmap, and assembly experiment.

README.md: refreshed to v0.1 baseline status. Quick-start uses the
real flow (uv sync, migrate-fresh, dev, /health, artifactstore health).
Make targets and CLI commands tabulated. Links docs/OPERATOR.md.

AGENTS.md: Current Repo Shape now reflects the landed scaffold +
library + CLI + HTTP app rather than "no runnable scaffold yet";
links OPERATOR.md and lists the canonical local commands.

workplans/ARTIFACT-STORE-WP-0001-service-baseline.md:
- T008 marked done.
- frontmatter status: active -> done; updated: 2026-05-16.

All ten WP-0001 tasks are now done (T001/T002/T003/T008/T009/T010/
T011/T012/T013/T014). Foundation workplan retires.

Gates: ruff clean, mypy --strict clean, 83 tests pass.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-16 09:02:36 +02:00
fe47058e1f WP-0001-T014: minimal HTTP app and CLI
src/artifactstore/app.py (new): composition root. build_registry(settings)
wires AsyncEngine + LocalBackend + InProcessDataPlane + RegistryViewWriter
into a Registry. Used by both the HTTP app and the CLI.

src/artifactstore/registry/__init__.py: adds db_health() (SELECT 1 probe),
backend_health() (pass-through to dataplane), and dispose() (engine
shutdown) helpers so the HTTP /health endpoint and CLI commands can talk
to the registry without reaching for private state.

src/artifactstore/api/http/__init__.py:
- create_app(settings=None) factory; lifespan owns the registry instance
  and disposes it on shutdown.
- GET / returns the scaffold banner.
- GET /health reports overall status + db {healthy, detail} + backend
  {backend_id, healthy, detail, free_bytes, total_bytes}. Uses
  FastAPI Depends() with a request->state.registry helper rather than
  reaching app.state directly.
- Module-level `app = create_app()` so `uvicorn artifactstore.api.http:app`
  keeps working.

src/artifactstore/cli/__init__.py:
- migrate: `alembic upgrade head` via the alembic command API.
- replay: drops + rebuilds materialised views from the event log; prints
  the highest applied sequence.
- health: prints the same payload as the HTTP /health endpoint, as JSON.
- version unchanged.

Tests:
- tests/integration/test_http_health.py (TestClient-based): /
  scaffold banner; /health reports ok with db.healthy + backend.healthy
  + free_bytes populated.
- tests/integration/test_cli_commands.py (typer CliRunner): version
  prints; migrate creates the schema (events + retention_classes +
  alembic_version); replay against an empty log exits ok with
  "replayed up to sequence 0"; health prints a status=ok JSON payload.

Gates: ruff clean, mypy --strict clean on 48 files, 83 tests pass.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-16 08:56:13 +02:00
f59213f512 chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-16:
  - update .custodian-brief.md for artifact-store
2026-05-16 08:38:57 +02:00
847b146475 WP-0001-T013: registry orchestrator (library surface)
src/artifactstore/registry/__init__.py implements the Registry class with
six operations the HTTP API and CLI both consume:

* create_package(name, producer, subject, retention_class, actor, metadata?)
  -> UUID. Validates retention_class against the seed table; emits
  v1.package.created with CBOR payload; applies view in same transaction.
* ingest_file(package_id, relative_path, media_type, stream, actor) -> UUID.
  Validates the package is in 'created' status and rejects duplicate
  relative_path. Calls dataplane.ingest_stream (which dual-hashes and writes
  to the backend). Emits v1.file.ingested whose payload carries the file
  metadata + storage receipt + deterministic storage_location_id so replay
  reproduces UUIDs. View handler in events/views.py inserts artifact_files
  + storage_locations and bumps last_event_sequence on the package.
* finalize_package(package_id, actor) -> ContentAddress. Queries the views
  to build a Manifest dataclass, encodes it as canonical CBOR, computes the
  BLAKE3 content address, and writes v1.package.finalized whose payload IS
  the canonical CBOR manifest. The view handler now records
  manifest_digest = event.payload_digest (BLAKE3 of the manifest), not a
  separate field parsed from the payload.
* get_manifest_bytes(package_id, format='cbor'|'json') -> bytes. Reads the
  finalize event payload (CBOR) and optionally projects to JCS.
* get_file(file_id) -> AsyncIterator[bytes]. Looks up the storage location
  and serves bytes via the data plane.
* tail_events(since_sequence, poll_interval_seconds) -> AsyncIterator[Event].
  Pass-through to events.tail.

src/artifactstore/events/views.py:
- New v1.file.ingested handler.
- v1.package.finalized handler updated: manifest_digest now derived from
  event.payload_digest (= BLAKE3 of the canonical CBOR manifest payload).
- All inserts now pass created_at=event.created_at explicitly so replay
  produces byte-identical materialised state (server_default=now() was
  firing fresh on each replay insert).

tests/integration/test_registry.py (7 cases):
- Rejects unknown retention class.
- create_package writes the event and the package row.
- ingest_file writes file + storage_location, populates content_address
  with blake3 prefix.
- Duplicate relative_path raises DuplicateRelativePathError.
- ingest into unknown package raises PackageNotFoundError.
- Finalising twice raises IllegalPackageStateError.
- End-to-end: create + ingest 3 files + finalize + read manifest in CBOR
  and JSON + download each file with byte equality + tail 5 events + replay
  + assert byte-identical materialised state across pre and post snapshots.

tests/integration/test_event_log.py updated: the v1.package.finalized
replay test now uses the new payload semantics (payload is the canonical
CBOR manifest; manifest_digest = BLAKE3 of payload).

Gates: ruff clean, mypy --strict clean on 45 files, 77 tests pass.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-16 08:17:40 +02:00
48fd415330 chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-16:
  - update .custodian-brief.md for artifact-store
2026-05-16 02:23:09 +02:00
5ff02a2bf3 WP-0001-T012: data plane SPI and in-process implementation
src/artifactstore/dataplane/:
- spi.py: DataPlane Protocol with the five operations ingest_stream,
  serve_object, verify_object, delete_object, backend_health
  (ADR-0004). Dataclasses: IngestHints (size_hint, primary_algorithm,
  backend_id overrides), IngestResult (primary_digest + sha256_digest +
  size_bytes + StorageReceipt), VerifyResult (verified bool, mismatch
  reason, actual digests + size).
- inproc.py: InProcessDataPlane wraps one StorageBackend. ingest_stream
  is two-pass against a tempfile (drain stream while dual-hashing into
  BLAKE3+SHA-256, then forward the tempfile to backend.put under the
  primary content address); fsync+cleanup on exception. serve_object
  passes byte ranges through; verify_object re-reads bytes via backend.get,
  re-digests with the stored algorithm, and reports mismatches. delete
  and health are thin pass-throughs.

tests/unit/test_dataplane_inproc.py (11 cases):
- ingest_stream computes correct dual digests, returns receipt, stores
  bytes at the content-addressed path.
- empty-input ingest returns the BLAKE3/SHA-256 of empty.
- serve_object round-trips ingested bytes; supports byte_range.
- verify_object verifies intact bytes; detects on-disk corruption.
- delete_object passes through (True then False).
- backend_health passes through.
- IngestHints override of primary_algorithm (sha256-as-primary path).
- Missing-object serve raises ObjectNotFoundError.
- Architectural test (ADR-0004 invariant): no control-plane module
  (api / registry / retention / audit) imports
  artifactstore.storage.backends.* or artifactstore.dataplane.inproc
  directly. Enforced via AST scan of every .py file in those packages.

Gates: ruff clean, mypy --strict clean on 44 files, 70 tests pass.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-16 02:07:05 +02:00
3d50564d12 chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-16:
  - update .custodian-brief.md for artifact-store
2026-05-16 02:06:03 +02:00
28ec2922d3 WP-0001-T003: storage adapter SPI and local filesystem backend
src/artifactstore/storage/:
- spi.py: StorageBackend Protocol (backend_id, put, get, head, delete,
  health) and result dataclasses (StorageReceipt, StorageObjectMetadata,
  DeletionResult, BackendStatus). ObjectNotFoundError exception type.
- registry.py: backend lookup by string ID (register/get/list_backends/
  clear) per ADR-0004.
- backends/local.py: LocalBackend implementation.
  * Object layout <root>/<algorithm>/<hex[0:2]>/<hex[2:4]>/<hex>.
  * Atomic writes: tmpfile + fsync + rename (idempotent re-puts drain the
    stream without rewriting).
  * Defence in depth: resolves the final path and asserts it remains under
    the configured root.
  * Range reads honour HTTP-style inclusive (start, end) tuples.
  * health() returns disk usage via shutil.disk_usage and surfaces an
    unhealthy status when the root has disappeared.
  * delete() cleans up emptied shard directories opportunistically.

tests/unit/test_storage_local.py (14 cases): put/get round-trip; object
key layout matches blueprint; head returns metadata; head/get missing
raise ObjectNotFoundError; put is idempotent; delete returns True then
False; range read returns subrange; range read rejects invalid range;
health reports disk usage; health reports unhealthy when root vanished;
ContentAddress validation blocks path-traversal-flavoured inputs;
registry register/get/list/clear round-trip; idempotent re-put leaves
bytes intact.

Gates: ruff clean, mypy --strict clean on 41 files, 59 tests pass.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-16 02:01:25 +02:00