Skip to content

v1.0.0 release prep: federation hardening, secret scanner, CI gates#12

Merged
68 commits merged into
mainfrom
RC1
May 30, 2026
Merged

v1.0.0 release prep: federation hardening, secret scanner, CI gates#12
68 commits merged into
mainfrom
RC1

Conversation

@tachyon-beep

Copy link
Copy Markdown
Collaborator

Summary

40 commits' worth of v1.0.0 release-prep stack from main, broken into five logical groups:

  • WP5 pre-ingest secret scanner — full implementation + review-pass fixes (cd31bffbb23296).
  • Loom federation read-API hardening — C0–C19 task series: storage correctness, error classification, capability handshake with instance_id, runtime trust model, fixtures (ad37c50a1a0399).
  • Sprint 3 federation hardening — bearer auth on /api/v1/files, POST /api/v1/files/batch, 403 BRIEFING_BLOCKED (replaces 404 masking), per-project instance_id propagation, path-normalization docs (1109560, acbf465, eb6200d, 2c3311a).
  • 1.0 release prep — Python plugin bumped to 1.0.0 with Beta classifier, CHANGELOG, README, operator guides, design-ladder rebrand to v1.0 (a28c3a2, 536e882).
  • Pre-tag fixes from this review pass — five commits split into release-blockers (B-batch) and important hygiene (I-batch):
    • 69ba01f fix(llm_provider): always pass --tools so ADR-013 no-tools posture is mechanically enforced.
    • 98b5bbd ci(release): verify gate mirroring ci.yml; portable sha256/shasum; dynamic sdist filename; drop unused workflow_dispatch.inputs.tag; cross-workspace + Python-internal version-lockstep guards.
    • 64e1062 docs(release): rebrand the v0.1 design ladder titles to v1.0; soften the "Tagged at v1.0.0" claim until the tag is actually pushed.
    • fcef6a0 docs(adr): ADR-034 retroactively pins the Sprint 3 federation hardening (bearer auth, batch endpoint, BRIEFING_BLOCKED, instance_id). ADR-014's Status field carries the only mutation allowed by the immutability rule — Accepted; partially extended by ADR-034 (Security Posture and Error Envelope sections only). contracts.md error-enum statement corrected to include BATCH_TOO_LARGE.
    • 30e7888 chore(release-hygiene): ADR count + ADR-008→ADR-012 typo, Sprint 3 closure in v0.1-plan.md, RUSTDOCFLAGS=-D warnings on the ci.yml doc step, cross-workspace check-workspace-version-lockstep.py.

Diff: ~15.4k lines across 151 files; majority is new documentation (ADRs, operator guides, sprint artefacts), federation contracts and fixtures, and the secret-scanner subsystem.

Pre-merge / pre-tag gates that the operator owns

These are surfaced from the review passes; merging this PR does NOT discharge them.

  1. F-1 lockstep window — filigree clarion-cd21b98463 (C-6 registry_backend rename). The coordinator memo of 2026-05-19 said Filigree's F-1 (registry-backend consumer parser) was uncommitted; re-verify before tag push that F-1 hasn't merged consuming the old field name since then.
  2. Tag pushv1.0.0 is deliberately NOT pushed by this PR. The new release.yml verify job + softprops/action-gh-release@v2 draft: false posture means a tag push directly publishes a public Release. Cut the tag manually after this PR merges and the F-1 status is confirmed.
  3. Out-of-scope (post-1.0) — supply-chain hardening (SLSA attestation, cosign signing, PyPI trusted publish, Linux aarch64) is tracked under filigree clarion-db0d25a5db (P3, label release:v1.1). Not blocking this merge.

Test plan

The CI side of this PR validates itself: the new release.yml verify job mirrors the same steps as ci.yml, and ci.yml gains RUSTDOCFLAGS=-D warnings plus the cross-workspace version-lockstep guard. Concretely:

  • ci.yml rust job: fmt → migration retirement → cross-workspace version lockstep (new) → clippy → build → nextest → doc (with RUSTDOCFLAGS=-D warnings, new) → cargo-deny.
  • ci.yml python-plugin job: ruff → ruff format → mypy --strict → pytest. The new test_plugin_version_lockstep_across_pyproject_manifest_and_module test must pass.
  • ci.yml walking-skeleton job: e2e walking skeleton + WP5 secret-scan smoke.
  • Manual: gh workflow run Release from RC1 to exercise the verify job without publishing a Release (the publish step is gated on event_name == 'push').
  • Manual pre-tag: confirm Filigree F-1 status (see gate 1 above).

🤖 Generated with Claude Code

tachyon-beep and others added 30 commits May 19, 2026 02:13
- Introduced CodexCliConfig and ClaudeCliConfig structs to manage configurations for Codex and Claude CLI providers.
- Updated LlmConfig to include new CLI configurations and modified default implementations.
- Enhanced LlmProviderKind enum to support new Codex CLI and Claude CLI providers.
- Implemented provider selection logic for Codex CLI and Claude CLI, requiring live opt-in for usage.
- Added tests to validate the behavior of Codex CLI and Claude CLI providers under various configurations.
- Updated documentation to include details on configuring and using Codex CLI and Claude CLI providers.
- Enhanced usage statistics to track cached input tokens for better performance metrics.
Add Clarion WP10 HTTP read endpoints, federation contract artifacts, Sprint 3 closeout docs, and WP5 secret scanner review fixes.
…ementation/

Move scattered planning, review, and agent-handoff material into a single
labeled archive under docs/implementation/ so the release-facing tree
(docs/{suite,clarion/v0.1,clarion/adr,operator,federation}/) only surfaces
canonical material:

  docs/clarion/v0.1/plans/     -> docs/implementation/v0.1-scope-plans/
  docs/clarion/v0.1/reviews/   -> docs/implementation/v0.1-reviews/
  docs/superpowers/handoffs/   -> docs/implementation/handoffs/
  docs/superpowers/plans/      -> docs/implementation/agent-plans/
  docs/arch-analysis-2026-05-18-1244/
                               -> docs/implementation/arch-analysis-2026-05-18-1244/

Update path references in retained docs (suite/, clarion/adr/*, clarion/v0.1/*.md,
clarion/{README,adr/README}.md, docs/README.md) to point at the new locations.
Fix internal cross-references in moved docs whose depth changed. Patch two
pre-existing broken refs in agent-plans/ while in the area.

Rewrite docs/implementation/README.md as the archive index. Update
docs/clarion/v0.1/README.md, docs/clarion/README.md, and docs/README.md to
describe the archive as non-normative supporting context.

Refresh stale "Clarion: not yet built" facts in docs/suite/briefing.md to
reflect the Sprint-1 walking-skeleton ship state (tag v0.1-sprint-1).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ADR-013: harden pre-ingest secret scanner contracts, audit evidence, MCP briefing-block signals, and operator docs.

Verification: cargo fmt --all -- --check; cargo clippy --workspace --all-targets --all-features -- -D warnings; cargo build --workspace --bins; cargo nextest run --workspace --all-features; RUSTDOCFLAGS="-D warnings" cargo doc --workspace --no-deps --all-features; cargo deny check; bash tests/e2e/sprint_1_walking_skeleton.sh; git diff --check.
…docset

Touch only retained release-facing docs (docs/{suite,clarion/v0.1,clarion/adr}/);
no decision changes. Edits are status-line, link-target, or path-citation
corrections reflecting state since the 2026-04-18 design baseline.

Suite:
- loom.md §9: Clarion status was "Designed; implementation not yet started" —
  update to walking-skeleton-merged / v0.1-build-in-flight to match the
  briefing.md fix.

ADR cross-references that were "(pending)" for ADRs since Accepted:
- ADR-011 → ADR-005 (now Accepted)
- ADR-012 → ADR-005 (now Accepted)
- ADR-021 → ADR-012 (now Accepted)

ADR body-text path citations updated to the centralized archive layout:
- ADR-024: "docs/superpowers/plans/ and docs/clarion/v0.1/reviews/"
  → "docs/implementation/ (agent-plans/, v0.1-reviews/)"
- ADR-026: "docs/superpowers/handoffs/..." → "docs/implementation/handoffs/..."
- ADR-015: inline-code v0.1-scope-commitments.md path → new archive path
- ADR-023, adr/README.md: stale link display-text matched to relocated URL.

v0.1 design docset:
- system-design.md §12 "Writing cadence": ADR backlog list was 2026-04-18
  baseline state; reflect that ADR-023–ADR-032 are post-baseline and live
  in the ADR index, ADR-008 is Superseded.
- detailed-design.md §11: add coverage note that the navigation table reflects
  baseline ADR-001–ADR-022 only; refer post-baseline ADRs to the index.
- requirements.md, detailed-design.md preambles: add ADR-README pointer;
  label pre-restructure reviews as archived.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Reconciles CON-FILIGREE-02 against the Sprint 2 scope amendment (WP9-B +
WP10 deferred to v0.2). The constraint is rewritten to describe v1.0's
shadow-registry mode and forward-points to the amendment. The reqs that
the amendment defers also get a deferral banner inline so future readers
see the v1.0/v2.0 split at the requirement boundary, not just in the
amendment memo:

  - REQ-FINDING-03/04/05/06 (Filigree-side findings + dedup + SARIF)
  - REQ-INTEG-FILIGREE-01/02/03/04/05 (cross-product wire surfaces)

Closes filigree clarion-066f90d0dc.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Closes the v1.0 publish track (clarion-443320f078 Thread 1: B.1, B.2, C.2,
C.3, WS-D). The external-operator smoke test surfaced four publish-blocker
bugs in the documented happy path; all are fixed in this commit.

Docs / release ergonomics
  - README.md at repo root (B.1, clarion-380250e6ed). v1.0 framing, the
    seven MCP tools as a table, quick-start, project layout, contributing
    pointer.
  - docs/operator/getting-started.md (B.2, clarion-459e186028 +
    C.3 clarion-6150779248). Single-flow tutorial: install, analyse a
    small repo, connect MCP client, ask three pre-scripted questions,
    verify secret-block. Plugin-discovery PATH guidance folded in.
  - ADR-033 — v1.0 distribution via GitHub Releases (Linux x86_64 +
    macOS x86_64/aarch64; promote to crates.io/PyPI at v2.0). Windows is
    explicitly out (setrlimit is Unix-only).
  - .github/workflows/release.yml — tag-triggered binary matrix + Python
    sdist + SHA256s + auto-generated notes. workflow_dispatch supported
    for rc1 validation without a tag push.
  - LICENSE (MIT) materialised at repo root.

Source fixes surfaced by WS-D (clarion-3e0e481ef7)

  1. install.rs: the `clarion.yaml` stub used Rust `\<newline>` string
     line-continuations, which strip leading whitespace — the file shipped
     unindented and YAML-invalid. Switched to raw newlines + explicit
     indentation with a leading comment warning against the pattern.

  2. writer.rs / writer_actor.rs: `clarion analyze` was not idempotent —
     a second invocation against an unchanged corpus crashed with
     `UNIQUE constraint failed: entities.id`. The entity-insert path now
     UPSERTs on `id`, preserving `created_at` + `first_seen_commit` and
     refreshing the rest from the latest run's record. Matches the
     `INSERT OR IGNORE` discipline already in `insert_edge`. New
     regression test: `insert_entity_is_idempotent_across_runs`.

  3. discovery.rs: pipx-installed plugins live behind a symlink in
     `~/.local/bin/` pointing to `~/.local/share/pipx/venvs/<pkg>/bin/`,
     with the manifest under that venv's `share/clarion/plugins/...`.
     Plain install-prefix lookup from `~/.local/bin/` looked at
     `~/.local/share/` and missed the manifest entirely. Added a
     symlink-resolved install-prefix fallback that canonicalises the
     executable and retries the lookup under the resolved prefix.

  4. cli.rs: `clarion analyze --help` text still claimed "Sprint 1: no
     plugins are loaded". Rewritten to describe v1.0 behaviour, including
     the idempotency contract and the `skipped_no_plugins` exit-0
     diagnostic.

Version + attribution
  - Workspace + path-deps + plugins/python: 0.1.0-dev → 1.0.0.
  - OpenRouter attribution `referer` defaults: qacona/clarion →
    tachyon-beep/clarion across crates + docs + tests.

Closes filigree clarion-380250e6ed, clarion-459e186028,
clarion-6150779248, clarion-25f5ff9de0, clarion-3e0e481ef7.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- AGENTS.md: per-repo agent instructions anchor written by `filigree doctor`
  on first invocation under v2.0.3.
- .mcp.json: auto-reformatted by filigree-mcp (whitespace normalisation +
  trailing newline + dropped redundant empty `env`); no functional change.
C1 — HTTP /api/v1/files now refuses briefing-blocked entities.
resolve_file surfaces briefing_blocked from properties_json via the new
entity_briefing_block_reason helper; http_read::get_file returns 404 + an
audit tracing::warn! instead of leaking the entity_id/content_hash. Storage
contract covered by three query_helpers tests. The federation read surface
is now consistent with MCP summary/callers_of_inferred which already gate
on this property. Integration test for the HTTP surface is filed separately
(clarion-5d6c01fe1a) — the spawn-serve harness hangs on the blocked-entity
codepath, root cause TBD.

C2 — Sidecar walk for .env/.env.* files now logs each walk error and
emits a tail count, mirroring analyze.rs::collect_source_files. Filtering
walk errors with filter_map(Result::ok) hid ACL/perm/dangling-symlink
failures from the security gate.

C3 — Claude CLI provider no longer falls back to raw stdout when no
`result` event or `structured_output`/`structuredOutput`/`result` field is
present. Both the event-selection step and claude_structured_output_json
now return InvalidResponse (retryable) so callers do not persist event
payloads as summaries.

C4 — docs/operator/secret-scanning.md no longer references a non-existent
`--no-llm` flag; the real control is `llm.allow_live_provider: false` or
leaving `CLARION_LLM_LIVE` unset, both of which keep the recording
provider as the only dispatch path.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
I13 — secret-scan finding-anchor `file_content_hash` now logs a tracing::warn!
naming the path + error when fs::read fails. The anchor still lands without
a content_hash but the audit trail records why, including the hint that
entity briefing-block lookups may fail for that path.

I14 — `parse_codex_jsonl_usage` no longer silently swallows malformed JSONL
lines. Each malformed line logs a warn with the parse error and an 80-char
snippet; a tail-warn reports the total skipped count and flags that
`session_token_ceiling` enforcement will diverge from true accounting until
those lines are recoverable.

I15 — `plugin::host::apply_briefing_block` now removes any plugin-supplied
`briefing_blocked` entry from `raw.extra` before optionally inserting the
scanner-authored one. The scanner is the sole authority for this property;
a malicious or buggy plugin cannot unblock an entity by emitting
`"briefing_blocked": <anything>` and cannot over-block by injecting a
reason the scanner did not assign.

I16 — `CodexCliProvider::from_config` and `ClaudeCliProvider::from_config`
now validate the configured `executable` via `which::which` at construction
time. A typo in `clarion.yaml` aborts at `clarion serve` startup with
`LlmProviderError::Cli` (non-retryable) rather than exploding on the first
MCP request. New workspace dependency: `which = "6"`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
`pre_ingest` now emits the per-detection `CLA-SEC-SECRET-DETECTED` finding
unconditionally — both when the operator overrides and when the file is
blocked. The override finding `CLA-SEC-UNREDACTED-SECRETS-ALLOWED` remains
additive, recording the operator decision and the detection list as
evidence, but no longer replaces the per-(rule,file,line) audit row.

ADR-013 §"Override — --allow-unredacted-secrets" specifies this shape:
"each affected file emits `CLA-SEC-UNREDACTED-SECRETS-ALLOWED` (severity
ERROR)" *in addition to* the per-detection `CLA-SEC-SECRET-DETECTED`. The
prior code suppressed `CLA-SEC-SECRET-DETECTED` in the override branch and
hid the audited population from
`filigree list --rule-id=CLA-SEC-SECRET-DETECTED` — precisely the query a
security review would run.

Tests updated:

- `non_tty_override_confirmed_allows_briefing_and_records_stats` now asserts
  `secret_count == 1` alongside `override_count == 1`.
- `baseline_suppression_and_override_admission_are_audited_together` now
  asserts `secret_count == 1` (the live overridden detection; the
  baseline-suppressed fixture contributes 0).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
I6 — `baseline_does_not_suppress_when_hash_drifts_at_same_line` pins the
"baseline benign at line 1, file mutated to a *different* secret at line 1"
case. Suppression keys on (hashed_secret, line_number, rule_type); the
regression net was missing.

I7 — `high_entropy_hex_fires_on_lockfile_shas_but_baseline_suppresses_them`
documents the v0.1 path for HighEntropyHex false positives. Lockfile
integrity hashes and git SHA-1s fire the rule (40-char hex / entropy ≥ 3.0);
tightening the rule would let real low-entropy secrets through, so the
accepted resolution is the operator-baseline workflow already shipped under
ADR-013. The fixture asserts both fixtures suppress cleanly via baseline.

I10 — Five new unit tests for CLI provider failure paths:
- claude_cli_parser_rejects_empty_stdout_as_retryable_invalid_response
- claude_cli_parser_rejects_non_json_stdout
- claude_cli_parser_refuses_raw_stdout_when_no_structured_output_or_result_event
  (the §C3 contract: stdout without a `result` event or
  `structured_output`/`structuredOutput`/`result` field returns
  InvalidResponse, not a persisted raw payload)
- claude_cli_parser_accepts_result_event_with_string_result_payload
- cli_status_retryable_treats_signal_kill_as_retryable
- cli_status_retryable_treats_clean_nonzero_exit_as_non_retryable

I11 — `tests/e2e/wp5_secret_scan.sh` now exercises four new scenarios beyond
the happy path: baseline-suppression flow, confirmed
`--allow-unredacted-secrets` admission (asserting both SECRET_DETECTED and
UNREDACTED-SECRETS-ALLOWED land per §I5), malformed-baseline abort (exit
non-zero, no runs row), retry-after-baseline-add (operator workflow: block
→ commit baseline → re-run unblocks).

I12 — `McpConfig::from_yaml_str` rejects configs that name both `llm` and
`llm_policy` at the top level with a new `ConfigError::AmbiguousLlmKey`
(code `CLA-CONFIG-AMBIGUOUS-LLM-KEY`). Serde-norway aliases silently pick
one, which was the classic copy-paste-migration pitfall the review flagged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Project rule: name the function, not the work-package label. WP-task tags
leak from the implementation tracker into operator-facing surfaces and into
comments that will rot once WP5 is closed.

Replaced:
- docs/operator/secret-scanning.md: "WP5 audit surface" → "scanner audit
  surface"
- crates/clarion-cli/src/main.rs: ".env-supplied RUST_LOG ... before WP5's
  pre-ingest secret gate runs" → "... before the pre-ingest secret scanner
  runs"

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…a885)

rustfmt: wrap the 80-char `br#"..."#` literal in the InvalidResponse parser
test onto a continuation line.

clippy::doc-markdown: backtick the (hashed_secret, line_number, rule_type)
tuple identifiers in the baseline-drift test docstring.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
resolve_file now fails closed when no cataloged kind='file' entity exists for the source path, instead of deriving a file identity from module/function anchors.

ADR-003 forbids '@' in entity identifiers, so Clarion must not manufacture core:file:{hash}@{path} IDs. The federation read path should return the stored file entity ID or no file.
Resolve deleted-on-disk catalog rows from stored entity data without requiring candidate file canonicalization.

Propagate hash fallback read failures instead of returning an empty content_hash when the catalog has no hash.

Prefer catalog/plugin and extension language inference before caller-supplied language fallback.
CONTRACT-3 of the Loom federation read API: stop masking briefing-blocked
file entities as 404 NOT_FOUND. Filigree needs to distinguish "Clarion does
not know this file" (404) from "Clarion knows this file but refuses to
expose it" (403) — the second case is actionable (escalate / wait for
re-scan) while the first is a registry-coverage gap.

Wire surface:
  GET /api/v1/files?path=blocked.py
  -> 403 Forbidden
  -> {"error": "entity is briefing-blocked and cannot be exposed",
      "code": "BRIEFING_BLOCKED"}

The 403 envelope deliberately does not include entity_id, content_hash,
canonical_path, or language, so Filigree cannot infer file identity from
a refused entity (the whole point of the block).

The closed error-code enum gains BRIEFING_BLOCKED and (in anticipation of
CONTRACT-2 bearer auth) UNAUTHORIZED. The federation fixture
`get-api-v1-files.demo-python.json` adds a `briefing_blocked_403` example
and widens the error_envelope status_any and code enum.

Side note: the `tracing::warn!` originally written inline at the 403
branch hangs the HTTP handler because the file's tracing convention is to
route every handler-side event through `HTTP_ERROR_DISPATCH` via
`tracing::dispatcher::with_default(...)`; a bare macro emits through the
process-wide global dispatcher and (under axum's TraceLayer-created span)
deadlocks until the request times out. The new `log_briefing_blocked_refusal`
helper follows the file's existing wrap pattern (see `log_read_server_error`).

This commit also bundles in-flight parallel-session work that was on the
working tree when the briefing-blocked change landed and that the contract
fix transitively depends on:
- `CanonicalProjectPath` newtype on `ResolvedFile.canonical_path` (proven
  project-relative POSIX string at the type level).
- `InstanceId` newtype around the project UUID, replacing String at
  load/serve boundaries.
- `ReaderPool::identity()` and `HttpReadServer::readers_identity` so a
  refactor that re-opens the pool inside `run_http_read_server` fails
  loud rather than silently splitting reader state. The identity is
  captured *inside* the HTTP thread and shipped back to the supervisor
  via a new `HttpReadReady` ready-signal payload.
- `CatchPanicLayer` + `format_dyn_error_chain`-backed panic for
  unenumerated middleware `BoxError` variants, so a future regression
  surfaces as a hard panic-then-500 rather than a silent string-formatted
  500.

These were WP5 type-design follow-ups (clarion-2533594d79) running in a
parallel session; bundling here was the lowest-friction path to keep the
RC1 working tree green before tomorrow's federation prototype.

Tests:
- serve_http_files_endpoint_returns_briefing_blocked_for_blocked_entity
  (new) asserts 403 + BRIEFING_BLOCKED code + absence of identity fields
  from the response body.
- serve_http_responses_match_federation_fixture_contracts (existing) now
  also validates the new `briefing_blocked_403` example end-to-end via
  the fixture-driven walker (seeded via the new
  `seed_briefing_blocked_file_entity` helper).
- Full clarion-cli serve suite: 22/22 passing.

Refs: ADR-014, Filigree task clarion-18b7c476b4 (C-2).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e56834151a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

while IFS= read -r -d '' asset; do
digest=$(sha256sum "$asset" | cut -d' ' -f1)
printf '%s %s\n' "$digest" "$(basename "$asset")"
done < <(find artifacts -name 'clarion-*.tar.gz' -print0 | sort -z) > rust-subjects.txt

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Restrict provenance subjects to Rust archives

The subject collector currently hashes every clarion-*.tar.gz artifact, which also matches the Python sdist produced by build-plugin (clarion-plugin-python-...tar.gz from project.name = "clarion-plugin-python"). That means rust-subjects is no longer Rust-only, so the clarion-rust-binaries.intoto.jsonl provenance can include non-Rust assets and break downstream verifiers that expect only the Rust target archives. Tightening this glob to the Rust archive naming pattern avoids publishing an incorrectly scoped attestation.

Useful? React with 👍 / 👎.

Comment on lines +426 to +430
let Ok(body_bytes) = to_bytes(body, HTTP_BODY_LIMIT_BYTES).await else {
return json_error(
StatusCode::BAD_REQUEST,
ErrorCode::InvalidPath,
"request body is invalid",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve 413 semantics on HMAC-authenticated oversized bodies

When serve.http.identity_token_env is configured, protected requests are read in require_hmac_identity via to_bytes(...); any read error is currently collapsed to 400 INVALID_PATH. For bodies above the 16 KiB cap, this path returns 400 instead of the documented/expected transport-level 413, so clients cannot reliably distinguish malformed JSON from size-limit violations once HMAC auth is enabled.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 70a759693d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".


fn request_log_context(headers: &HeaderMap) -> RequestLogContext {
RequestLogContext {
loom_component: log_header_value(headers, "x-loom-component"),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Stop logging HMAC auth header values

When serve.http.identity_token_env is enabled, X-Loom-Component carries the request HMAC (clarion:<hex>), but this code copies that raw header into the tracing span, so auth material is written to logs. Because the signed message has no nonce/timestamp, the same signature is replayable for the same method/path/body; log readers can reuse captured signatures to call protected endpoints. Redact this header (or log only presence/component name) instead of recording the full value.

Useful? React with 👍 / 👎.

- Introduced comprehensive architecture diagrams in 03-diagrams.md, detailing C4 context, container view, analyze pipeline, serve and query flow, trust boundaries, and release lane.
- Created 04-final-report.md to assess the architectural coherence of RC1, highlighting strengths, risks, and recommendations for release readiness.
- Added 05-quality-assessment.md to evaluate the overall quality posture, maintainability, correctness, operability, and documentation quality of the RC1 codebase.
- Developed 06-architect-handover.md for seamless transition to new architects, summarizing current state and release gate calls.
- Compiled 07-security-surface.md to outline the security posture, trust boundaries, positive controls, and concerns related to the RC1 architecture.
- Documented 08-release-readiness.md to summarize the release readiness verdict, ready signals, blocking items, and recommended release sequence.
- Created 09-test-infrastructure.md to map test coverage across various areas and identify gaps and risks in the testing strategy.
- Added 10-dependency-analysis.md to analyze internal dependencies, external dependencies, and associated risks.
- Included temporary task documents for subsystem analysis of `clarion-cli`, `clarion-core`, `clarion-mcp`, `clarion-storage`, and the Python plugin.
- Validated subsystem catalog and diagrams, ensuring alignment with architecture and quality standards.
@tachyon-beep tachyon-beep closed this pull request by merging all changes into main in 24916e0 May 30, 2026
@tachyon-beep
tachyon-beep deleted the RC1 branch June 5, 2026 07:32
tachyon-beep added a commit that referenced this pull request Jun 8, 2026
… serve, config passthrough (clarion-c326ee6857)

Implements the 4 still-valid deferred findings from the PR#21 review; the
other 8 were verified already-fixed/outdated against current code (rc3) and
need only thread resolution (recorded on the issue).

#4 writer.rs begin_run TOCTOU: if begin_write_tx exhausts its retries after the
runs row was auto-committed 'running', re-mark the row 'failed' under a fresh
implicit tx (mirrors the CommitRun failure-remark idiom) so it isn't stranded
phantom-running with current_run unset. Deliberately does NOT move the INSERT
inside the tx (the ticket's literal suggestion) — that would hide the running
row from cross-process analyze_status until the first batch COMMIT (the
regression review #15 warns about). Best-effort; mark_stale_running_runs_failed
remains the startup backstop.

#15 writer.rs resume_run: capture the row's prior (status, completed_at) before
flipping it to 'running' and restore them if begin_write_tx fails — a
pre-existing completed run must not be left flipped to running.

Both paths get deterministic, single-threaded coverage via two test seams
(grab a competing write lock after the insert/update; release it on the
failure path so the best-effort cleanup can re-acquire the lock) — the
contention harness the ticket said #4/#15 needed, without threads or
wall-clock races.

#8 reader.rs open_validated: reject an unmigrated DB (new
schema::reject_unmigrated_for_read → StorageError::UnmigratedIndex) so a
header-valid but empty/externally-created file is refused at serve instead of
auto-materialised and answered with zero rows. Keyed on user_version (0 =
unmigrated), NEVER on row counts — an installed-but-unanalyzed index is
user_version=CURRENT with zero entities and stays a valid serve target.

#12 serve --config passthrough: serve forwards its resolved on-disk --config to
analyze_start-spawned analyze (ServerState::with_analyze_config →
spawn_analyze --config) so the child parses the same configuration the
operator launched serve with, instead of re-discovering config and silently
diverging.

Tests: 2 writer failpoint tests, 2 reader schema-validation tests, 1
spawn_analyze --config forward/omit test. 972 storage+mcp+cli tests green;
clippy -D warnings clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants