Skip to content

decisions: refresh all areas - #3727

Open
migmartri wants to merge 5 commits into
chainloop-dev:mainfrom
migmartri:decisions-refresh-2026-10-25
Open

migmartri wants to merge 5 commits into
chainloop-dev:mainfrom
migmartri:decisions-refresh-2026-10-25

Conversation

@migmartri

@migmartri migmartri commented Oct 25, 2026 •

Copy link
Copy Markdown
Member

Adds the first Current Decisions pages in docs/decisions/: the decisions and the words of each functional area that hold today, derived from the specs in docs/specs/, the issue states, and the code.

Areas

Open conflicts

  • Trace: pasted images are saved by the CLI (issue-3569 D-001). Only the agent wording differs: issue-3569 D-004 keeps the agent instruction to capture them (for role and title), and the code follows issue-3515 D-009 (the agent does not).
  • Trace: issue Spec capture: skip prompts that are already in the transcript, and capture specs written during the session #3515 is open, but its decisions are already in the code.
  • Trace: generated-line counts are already in the evidence (feat(trace): report the generated line totals of a session #3680). issue-3639 D-011 left them to a later spec.
  • Trace: issue-3639 D-003 (joined-line fingerprints in commit records) and D-012 (commit record retention) drift from the code.
  • Trace: issue-3639-line-ranges D-005: the schema and the writer shipped in the same release.
  • Trace: the end-to-end suite has no nightly CI job, no Slack report, and does not install the pinned harness versions (issue-3635).
  • Artifact CAS: the 24-hour existence cache lifetime is not configurable (issue-3543 D-007). The client cache reloads on any error, not only on an authentication error (D-009).
  • Authentication: the browser download login now uses the handoff code (issue-3626 D-008).
  • Service endpoints: the CAS follows issue-3628-single-endpoint D-020 (shared endpoint, feat(cas): shared HTTP and gRPC endpoint via per-request dispatch and a reverse proxy to the native transport #3663), against issue-3628-controlplane-http-dispatch D-003 (separate endpoints). D-003 is not marked as replaced.
  • Service endpoints: D-020 removes the separate-connection contract of D-014 for the CAS, but D-014 is not struck.
  • Service endpoints: issue Serve gRPC and HTTP from one endpoint per service #3628 is open. Left: the deprecation dates and steps (D-007, D-003), the end of the two-Service chart layout (D-004), the move of the control plane's CAS connection to the single port (D-012), and proxy tests in CI (D-015).
  • Artifact CAS: the existence cache has no off switch (issue-3543 R-004).
  • Attestation CLI: issue feat: allow to force project and organization in .chainloop.yaml #3063 is open, but all checked decisions are built. The code adds one step to the organization order (local attestation state before the saved default).

Review

Each area owner approves the map entry, the key decision cut, and the Language of their area. This is the first Current Decisions PR of the repository, so please also check the owner of each area.

AI assistance: this PR was produced with Claude Code.

Generate docs/decisions with eng-spec --decisions: the area map and one page per area (Trace, Attestation CLI, Artifact CAS, Service endpoints, Authentication), with code states and open conflicts.

Assisted-by: Claude Code
Signed-off-by: Miguel Martinez Trivino <miguel@chainloop.dev>

Chainloop-Trace-Sessions: 2fa80ea8-adee-42d4-8d71-2b2419570719
@migmartri
migmartri requested a review from jiparis October 25, 2026 21:20
@chainloop-platform

chainloop-platform Bot commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor

PR validation — ⚠️ 1 failing

Status Policy Material Messages
⚠️ Failed pr-min-approvals pr-info PR/MR #3727 has 0 approving reviews, 1 required.
✅ Passed pr-description-required pr-info -
✅ Passed pr-user-story-linked pr-info -

View attestation ↗

AI Session Checks — 🟢 81% · ✅ 0 failing

Avg score Sessions Failing policies Attribution Files Lines Total Duration
🟢 81% 1 ✅ 0 100% AI / 0% Human 6 +770 / -0 20h33m40s

🟢 81% — 100% AI — ✅ All policies passing

Oct 25, 2026 21:07 UTC · 20h33m40s · $49.66 · 1.6k in / 642.2k out · claude-code 2.1.310 (claude-opus-5-5)

View session details ↗

Change Summary

  • Adds docs/decisions/README.md plus five area pages for Trace, Attestation CLI, Artifact CAS, Service endpoints, and Authentication.
  • Records current decisions, language, code-state summaries, superseded entries, and open conflicts from existing specs.
  • Converts decision entries to the newer heading-based format with Why, Rejected, Source, and Code lines.

AI Session Overall Score

🟢 81% — Strong docs-only refresh, but verification evidence stops at unproven check summaries.

AI Session Analysis Breakdown

🟢 95% · scope-discipline

🟢 All six changed files are the expected docs/decisions outputs. · High Impact

🟢 90% · user-trust-signal

🟢 The user returned with more work instead of abandoning the run. · High Impact

🟢 88% · alignment

No notes.

🟢 86% · context-and-planning

🟢 Task and format docs were captured before the bulk of editing. · High Impact

🟢 84% · solution-quality

No notes.

🟡 62% · verification

🟠 Verification rests on reported code-check summaries, not captured execution or reproducible outputs. · Medium Severity

💡 When checks drive the page states, capture the supporting commands or outputs in-session.


File Attribution

████████████████████ 100% AI / 0% Human

Status Attribution File Lines
created ai docs/decisions/trace.md +406 / -0
created ai docs/decisions/service-endpoints.md +106 / -0
created ai docs/decisions/artifact-cas.md +85 / -0
created ai docs/decisions/README.md +63 / -0
created ai docs/decisions/authentication.md +59 / -0
created ai docs/decisions/attestation-cli.md +51 / -0

Policies (4)

Status Policy Material Messages
✅ Passed ai-config-ai-agents-allowed ai-coding-session-2fa80e -
✅ Passed ai-config-no-dangerous-commands ai-coding-session-2fa80e -
✅ Passed ai-config-no-secrets ai-coding-session-2fa80e -
✅ Passed ai-config-mcp-servers-allowed ai-coding-session-2fa80e -

Security Checks — ✅ 5 passing

✅ secret-scan

Status Policy Messages
✅ Passed secrets-detection -

✅ sast-scan

Status Policy Messages
✅ Passed owasp-top10-2025 -
✅ Passed sast -
✅ Passed cwe-top25 -
✅ Passed cwe-top26-40-cusp -
Scans not applied (3)
Scan Reason
vulnerability-scan no manifest/lockfile changed
github-actions-scan no workflow files changed
iac-scan no IaC files changed

View attestation ↗

Security context

✅ Nothing this change touches has a recorded security-fix history.

View in Chainloop ↗ · How this works ↗


Powered by Chainloop and Chainloop Trace

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

4 issues found across 6 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="docs/decisions/trace.md">

<violation number="1" location="docs/decisions/trace.md:52">
P3: This row only says the agent's body stays over 1 MiB. It should also state that only a regular text file is read, and that a capture with no usable body (only the placeholder) is dropped with a warning.</violation>
</file>

<file name="docs/decisions/authentication.md">

<violation number="1" location="docs/decisions/authentication.md:19">
P3: These code references are relative to an unstated root, so they don't resolve from the repo root. Use the full repo paths, matching the Open conflicts entry: `app/controlplane/pkg/data/ent/schema/loginhandoff.go`, `app/controlplane/internal/service/auth.go`, and `app/controlplane/internal/service/casredirect.go`.</violation>
</file>

<file name="docs/decisions/attestation-cli.md">

<violation number="1" location="docs/decisions/attestation-cli.md:9">
P3: The file is not only read from the repository root. The reader walks up from the current directory to the git root and uses the nearest `.chainloop.yml`, per R-007. Say that instead of "at the root of a repository".</violation>
</file>

<file name="docs/decisions/service-endpoints.md">

<violation number="1" location="docs/decisions/service-endpoints.md:43">
P2: Open conflicts names only one CAS conflict. D-020 also contradicts the active Ingress shape (D-004) and Upstream connections (D-014) and Where multiplexing (D-015) rows for CAS. Add these as open CAS conflicts, or state that the rows do not apply to CAS.</violation>
</file>

Reply with feedback, questions, or to request a fix.

View guided diff | Re-trigger cubic

Comment thread docs/decisions/attestation-cli.md Outdated
Comment thread docs/decisions/service-endpoints.md Outdated

## Open conflicts

- **CAS shared endpoint and CAS transport.** [issue-3628-single-endpoint D-020](../specs/issue-3628-single-endpoint.md) gives the CAS a shared endpoint with per-request dispatch. [issue-3628-controlplane-http-dispatch D-003](../specs/issue-3628-controlplane-http-dispatch.md) keeps the CAS on its native transport and separate endpoints. Neither entry names the other. Proposed: the owner says which one holds, in the spec of the CAS work.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2: Open conflicts names only one CAS conflict. D-020 also contradicts the active Ingress shape (D-004) and Upstream connections (D-014) and Where multiplexing (D-015) rows for CAS. Add these as open CAS conflicts, or state that the rows do not apply to CAS.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At docs/decisions/service-endpoints.md, line 43:

<comment>Open conflicts names only one CAS conflict. D-020 also contradicts the active Ingress shape (D-004) and Upstream connections (D-014) and Where multiplexing (D-015) rows for CAS. Add these as open CAS conflicts, or state that the rows do not apply to CAS.</comment>

<file context>
@@ -0,0 +1,43 @@
+
+## Open conflicts
+
+- **CAS shared endpoint and CAS transport.** [issue-3628-single-endpoint D-020](../specs/issue-3628-single-endpoint.md) gives the CAS a shared endpoint with per-request dispatch. [issue-3628-controlplane-http-dispatch D-003](../specs/issue-3628-controlplane-http-dispatch.md) keeps the CAS on its native transport and separate endpoints. Neither entry names the other. Proposed: the owner says which one holds, in the spec of the CAS work.
</file context>
Suggested change
- **CAS shared endpoint and CAS transport.** [issue-3628-single-endpoint D-020](../specs/issue-3628-single-endpoint.md) gives the CAS a shared endpoint with per-request dispatch. [issue-3628-controlplane-http-dispatch D-003](../specs/issue-3628-controlplane-http-dispatch.md) keeps the CAS on its native transport and separate endpoints. Neither entry names the other. Proposed: the owner says which one holds, in the spec of the CAS work.
- **CAS shared endpoint and CAS transport.** [issue-3628-single-endpoint D-020](../specs/issue-3628-single-endpoint.md) gives the CAS a shared endpoint with per-request dispatch. [issue-3628-controlplane-http-dispatch D-003](../specs/issue-3628-controlplane-http-dispatch.md) keeps the CAS on its native transport and separate endpoints. Neither entry names the other. Proposed: the owner says which one holds, in the spec of the CAS work.
- **CAS ingress shape and upstream pools.** [issue-3628-single-endpoint D-020](../specs/issue-3628-single-endpoint.md) uses one catch-all Ingress and mixed upstream connections. [issue-3628-single-endpoint D-004](../specs/issue-3628-single-endpoint.md), [D-014](../specs/issue-3628-single-endpoint.md), and [D-015](../specs/issue-3628-single-endpoint.md) still require a second Ingress and separate upstream pools for CAS. Proposed: the owner states which one holds for CAS.

Comment thread docs/decisions/service-endpoints.md Outdated
Comment thread docs/decisions/service-endpoints.md Outdated
Comment thread docs/decisions/README.md Outdated
Comment thread docs/decisions/trace.md Outdated
| Certainty before removal | Replace a copy only when its material is in the CAS and the digest matches exactly | A wrong pointer loses evidence. Rejected: a match by size or name. | [issue-3556-session-image-placeholders D-010](../specs/issue-3556-session-image-placeholders.md) | verified: exact sha256 match in `claude/speccopies.go` |
| Scope of the replacement | Each exact copy of a spec source, all file types, from file reads and writes | One rule for images and text. Rejected: images only. | [issue-3556-session-image-placeholders D-013](../specs/issue-3556-session-image-placeholders.md) | verified: read and write tools both matched |
| How the push treats a local source | Read the file at push time and record its content | The record no longer depends on the agent. Rejected: warn on a difference. | [issue-3561-up-to-date-local-spec-evidence D-001](../specs/issue-3561-up-to-date-local-spec-evidence.md) | verified: `internal/trace/spec/local.go` |
| Size limit for a local file | 1 MiB. Over it, the agent's body stays | A spec is small text. | [issue-3561-up-to-date-local-spec-evidence D-006](../specs/issue-3561-up-to-date-local-spec-evidence.md) | verified: `maxLocalSourceSize` |

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P3: This row only says the agent's body stays over 1 MiB. It should also state that only a regular text file is read, and that a capture with no usable body (only the placeholder) is dropped with a warning.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At docs/decisions/trace.md, line 52:

<comment>This row only says the agent's body stays over 1 MiB. It should also state that only a regular text file is read, and that a capture with no usable body (only the placeholder) is dropped with a warning.</comment>

<file context>
@@ -0,0 +1,106 @@
+| Certainty before removal | Replace a copy only when its material is in the CAS and the digest matches exactly | A wrong pointer loses evidence. Rejected: a match by size or name. | [issue-3556-session-image-placeholders D-010](../specs/issue-3556-session-image-placeholders.md) | verified: exact sha256 match in `claude/speccopies.go` |
+| Scope of the replacement | Each exact copy of a spec source, all file types, from file reads and writes | One rule for images and text. Rejected: images only. | [issue-3556-session-image-placeholders D-013](../specs/issue-3556-session-image-placeholders.md) | verified: read and write tools both matched |
+| How the push treats a local source | Read the file at push time and record its content | The record no longer depends on the agent. Rejected: warn on a difference. | [issue-3561-up-to-date-local-spec-evidence D-001](../specs/issue-3561-up-to-date-local-spec-evidence.md) | verified: `internal/trace/spec/local.go` |
+| Size limit for a local file | 1 MiB. Over it, the agent's body stays | A spec is small text. | [issue-3561-up-to-date-local-spec-evidence D-006](../specs/issue-3561-up-to-date-local-spec-evidence.md) | verified: `maxLocalSourceSize` |
+| Who captures a pasted image | The CLI, at push time, from the image bytes in the transcript | The capture does not depend on the agent. Rejected: replace only the images the agent captured. | [issue-3569-pasted-image-pointers D-001](../specs/issue-3569-pasted-image-pointers.md) | verified: Claude Code and Codex finders (`trace_pasted_images.go`) |
+| Agent capture of pasted images | Keep the capture instruction. One entry per digest, and the agent's entry wins | The agent adds a role and a title. Rejected: take pasted images out of the instruction. | [issue-3569-pasted-image-pointers D-004](../specs/issue-3569-pasted-image-pointers.md) | drift: the agent entry wins by digest, but the instruction tells the agent not to capture pasted images. See Open conflicts |
</file context>
Suggested change
| Size limit for a local file | 1 MiB. Over it, the agent's body stays | A spec is small text. | [issue-3561-up-to-date-local-spec-evidence D-006](../specs/issue-3561-up-to-date-local-spec-evidence.md) | verified: `maxLocalSourceSize` |
| Size limit for a local file | 1 MiB, regular text files only. Over it, or for a non-text file, the agent's body stays. A capture with only the placeholder and no usable file is dropped with a warning | A spec is small text. | [issue-3561-up-to-date-local-spec-evidence D-006](../specs/issue-3561-up-to-date-local-spec-evidence.md) | verified: `maxLocalSourceSize` |

Comment thread docs/decisions/authentication.md Outdated
|----------|--------|-----|--------|------|
| Token delivery | A single-use handoff code that the client exchanges for the token | It takes the token out of the URL. | [issue-3626-login-code-exchange D-001](../specs/issue-3626-login-code-exchange.md) | verified: `ExchangeHandoff` in `internal/service/auth.go` |
| Code binding | PKCE-style S256 challenge from the client, plus the callback URL | Works for the CLI and a browser app, with no cookie at exchange. | [issue-3626-login-code-exchange D-002](../specs/issue-3626-login-code-exchange.md) | verified: S256 only, verifier and callback checked |
| Code store | Database table with the code hash, the user, the expiry, and an atomic consume. No token at rest | Works with many replicas and enforces single use. | [issue-3626-login-code-exchange D-004](../specs/issue-3626-login-code-exchange.md) | verified: `ent/schema/loginhandoff.go` |

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P3: These code references are relative to an unstated root, so they don't resolve from the repo root. Use the full repo paths, matching the Open conflicts entry: app/controlplane/pkg/data/ent/schema/loginhandoff.go, app/controlplane/internal/service/auth.go, and app/controlplane/internal/service/casredirect.go.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At docs/decisions/authentication.md, line 19:

<comment>These code references are relative to an unstated root, so they don't resolve from the repo root. Use the full repo paths, matching the Open conflicts entry: `app/controlplane/pkg/data/ent/schema/loginhandoff.go`, `app/controlplane/internal/service/auth.go`, and `app/controlplane/internal/service/casredirect.go`.</comment>

<file context>
@@ -0,0 +1,32 @@
+|----------|--------|-----|--------|------|
+| Token delivery | A single-use handoff code that the client exchanges for the token | It takes the token out of the URL. | [issue-3626-login-code-exchange D-001](../specs/issue-3626-login-code-exchange.md) | verified: `ExchangeHandoff` in `internal/service/auth.go` |
+| Code binding | PKCE-style S256 challenge from the client, plus the callback URL | Works for the CLI and a browser app, with no cookie at exchange. | [issue-3626-login-code-exchange D-002](../specs/issue-3626-login-code-exchange.md) | verified: S256 only, verifier and callback checked |
+| Code store | Database table with the code hash, the user, the expiry, and an atomic consume. No token at rest | Works with many replicas and enforces single use. | [issue-3626-login-code-exchange D-004](../specs/issue-3626-login-code-exchange.md) | verified: `ent/schema/loginhandoff.go` |
+| Deprecation | Three phases: allowed by default, then denied by default, then deleted | Operators get time and a measured deletion condition. | [issue-3626-login-code-exchange D-006](../specs/issue-3626-login-code-exchange.md) | verified: phase 1, with the `allow_legacy_login_callback` setting |
+| Browser artifact download flow | No change: it stays on the legacy callback | Its token expires after 10 seconds, and a separate change can move it. | [issue-3626-login-code-exchange D-008](../specs/issue-3626-login-code-exchange.md) | drift: the download flow now requires a handoff code and rejects `?t=` (`internal/service/casredirect.go`). See Open conflicts |
</file context>
Suggested change
| Code store | Database table with the code hash, the user, the expiry, and an atomic consume. No token at rest | Works with many replicas and enforces single use. | [issue-3626-login-code-exchange D-004](../specs/issue-3626-login-code-exchange.md) | verified: `ent/schema/loginhandoff.go` |
| Code store | Database table with the code hash, the user, the expiry, and an atomic consume. No token at rest | Works with many replicas and enforces single use. | [issue-3626-login-code-exchange D-004](../specs/issue-3626-login-code-exchange.md) | verified: `app/controlplane/pkg/data/ent/schema/loginhandoff.go` |


## Language

- **Repository config file**: `.chainloop.yml` at the root of a repository. When both `.chainloop.yml` and `.chainloop.yaml` exist, `.chainloop.yml` wins.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P3: The file is not only read from the repository root. The reader walks up from the current directory to the git root and uses the nearest .chainloop.yml, per R-007. Say that instead of "at the root of a repository".

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At docs/decisions/attestation-cli.md, line 9:

<comment>The file is not only read from the repository root. The reader walks up from the current directory to the git root and uses the nearest `.chainloop.yml`, per R-007. Say that instead of "at the root of a repository".</comment>

<file context>
@@ -0,0 +1,30 @@
+
+## Language
+
+- **Repository config file**: `.chainloop.yml` at the root of a repository. When both `.chainloop.yml` and `.chainloop.yaml` exist, `.chainloop.yml` wins.
+- **`projectName`** and **`organization`**: the keys that pin the project and the organization of a repository. _Avoid_: a `project` key, because `chainloop trace init` already writes `projectName`.
+- **Saved default**: the organization that the CLI configuration stores. It has the lowest precedence.
</file context>
Suggested change
- **Repository config file**: `.chainloop.yml` at the root of a repository. When both `.chainloop.yml` and `.chainloop.yaml` exist, `.chainloop.yml` wins.
- **Repository config file**: `.chainloop.yml`, read from the current directory up to the git repository root; the nearest file wins. When both `.chainloop.yml` and `.chainloop.yaml` exist in one directory, `.chainloop.yml` wins.

@migmartri
migmartri requested a review from a team October 25, 2026 21:26
…eded

Assisted-by: Claude Code
Signed-off-by: Miguel Martinez Trivino <miguel@chainloop.dev>

Chainloop-Trace-Sessions: 2fa80ea8-adee-42d4-8d71-2b2419570719

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

2 issues found across 1 file (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="docs/decisions/trace.md">

<violation number="1" location="docs/decisions/trace.md:39">
P3: This overstates current coverage: `pastedImageCaptures` returns nil when a provider lacks `PastedImageFinder`, and only Claude and Codex implement it. Qualify the statement to those providers.</violation>

<violation number="2" location="docs/decisions/trace.md:96">
P2: This page is generated and says not to edit it by hand, but this bullet and the removed Open conflict were hand-written. Regenerate the page from a spec instead. Also drop the unverifiable reference to PR #3727 review; the spec's decisions already show that export is out of scope (D-020).</violation>
</file>

Reply with feedback, questions, or to request a fix.

View guided diff | Re-trigger cubic

Comment thread docs/decisions/trace.md Outdated
- [issue-3582-trace-evidence-export D-010](../specs/issue-3582-trace-evidence-export.md) (a reserved local organization in the config), replaced by [issue-3582-trace-evidence-export D-013](../specs/issue-3582-trace-evidence-export.md).
- [issue-3582-trace-evidence-export D-013](../specs/issue-3582-trace-evidence-export.md) (a per-clone local marker), replaced by [issue-3582-trace-evidence-export D-018](../specs/issue-3582-trace-evidence-export.md).
- [issue-3582-trace-evidence-export D-015](../specs/issue-3582-trace-evidence-export.md) (ship `trace export` now), reversed by [issue-3582-trace-evidence-export D-020](../specs/issue-3582-trace-evidence-export.md).
- [issue-3582-trace-evidence-export D-011](../specs/issue-3582-trace-evidence-export.md), [D-012](../specs/issue-3582-trace-evidence-export.md), and [D-014](../specs/issue-3582-trace-evidence-export.md) (`trace run --export`, and a push hook that does nothing in favor of `trace export`), replaced by [issue-3582-trace-evidence-export D-016](../specs/issue-3582-trace-evidence-export.md), [D-017](../specs/issue-3582-trace-evidence-export.md), [D-020](../specs/issue-3582-trace-evidence-export.md), and [D-023](../specs/issue-3582-trace-evidence-export.md). Export is not built. The review of PR #3727 confirmed this.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2: This page is generated and says not to edit it by hand, but this bullet and the removed Open conflict were hand-written. Regenerate the page from a spec instead. Also drop the unverifiable reference to PR #3727 review; the spec's decisions already show that export is out of scope (D-020).

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At docs/decisions/trace.md, line 96:

<comment>This page is generated and says not to edit it by hand, but this bullet and the removed Open conflict were hand-written. Regenerate the page from a spec instead. Also drop the unverifiable reference to PR #3727 review; the spec's decisions already show that export is out of scope (D-020).</comment>

<file context>
@@ -93,12 +93,12 @@ Not shown: 6 smaller decisions of [issue-3495](../specs/issue-3495-session-spec-
 - [issue-3582-trace-evidence-export D-010](../specs/issue-3582-trace-evidence-export.md) (a reserved local organization in the config), replaced by [issue-3582-trace-evidence-export D-013](../specs/issue-3582-trace-evidence-export.md).
 - [issue-3582-trace-evidence-export D-013](../specs/issue-3582-trace-evidence-export.md) (a per-clone local marker), replaced by [issue-3582-trace-evidence-export D-018](../specs/issue-3582-trace-evidence-export.md).
 - [issue-3582-trace-evidence-export D-015](../specs/issue-3582-trace-evidence-export.md) (ship `trace export` now), reversed by [issue-3582-trace-evidence-export D-020](../specs/issue-3582-trace-evidence-export.md).
+- [issue-3582-trace-evidence-export D-011](../specs/issue-3582-trace-evidence-export.md), [D-012](../specs/issue-3582-trace-evidence-export.md), and [D-014](../specs/issue-3582-trace-evidence-export.md) (`trace run --export`, and a push hook that does nothing in favor of `trace export`), replaced by [issue-3582-trace-evidence-export D-016](../specs/issue-3582-trace-evidence-export.md), [D-017](../specs/issue-3582-trace-evidence-export.md), [D-020](../specs/issue-3582-trace-evidence-export.md), and [D-023](../specs/issue-3582-trace-evidence-export.md). Export is not built. The review of PR #3727 confirmed this.
 
 ## Open conflicts
</file context>
Suggested change
- [issue-3582-trace-evidence-export D-011](../specs/issue-3582-trace-evidence-export.md), [D-012](../specs/issue-3582-trace-evidence-export.md), and [D-014](../specs/issue-3582-trace-evidence-export.md) (`trace run --export`, and a push hook that does nothing in favor of `trace export`), replaced by [issue-3582-trace-evidence-export D-016](../specs/issue-3582-trace-evidence-export.md), [D-017](../specs/issue-3582-trace-evidence-export.md), [D-020](../specs/issue-3582-trace-evidence-export.md), and [D-023](../specs/issue-3582-trace-evidence-export.md). Export is not built. The review of PR #3727 confirmed this.
- [issue-3582-trace-evidence-export D-011](../specs/issue-3582-trace-evidence-export.md), [D-012](../specs/issue-3582-trace-evidence-export.md), and [D-014](../specs/issue-3582-trace-evidence-export.md) (`trace run --export`, and a push hook that does nothing in favor of `trace export`), replaced by [issue-3582-trace-evidence-export D-016](../specs/issue-3582-trace-evidence-export.md), [D-017](../specs/issue-3582-trace-evidence-export.md), [D-020](../specs/issue-3582-trace-evidence-export.md), and [D-023](../specs/issue-3582-trace-evidence-export.md). Export is not built.

Comment thread docs/decisions/trace.md Outdated
| Capture of a user prompt | Do not capture the user's request prompt. Capture a spec that the user pastes | The transcript holds the prompt. Rejected: keep it and label it "prompt". | [issue-3515-spec-capture-during-session D-001](../specs/issue-3515-spec-capture-during-session.md) | not built yet: parent issue #3515 is open. The code already does it (`trace_spec.go`) |
| How specs are found after session start | A short reminder at each user prompt | It keeps the agent as the decider and covers resumed sessions. Rejected: a general capture rule, and a hook that watches spec paths. | [issue-3515-spec-capture-during-session D-002](../specs/issue-3515-spec-capture-during-session.md) | not built yet: parent issue #3515 is open. The code already does it, with five cases (`trace_agent_hook.go`) |
| Spec file limit | 25 files. Never drop a file that an earlier push recorded | Long sessions get more specs, and the oldest are the start sources. Rejected: keep the newest files. | [issue-3515-spec-capture-during-session D-005](../specs/issue-3515-spec-capture-during-session.md) | not built yet: parent issue #3515 is open. The code already does it (`spec.MaxEntries`) |
| Pasted images (agent) | The agent does not capture a pasted image | A description is not the image. Rejected: a description of kind `image`. | [issue-3515-spec-capture-during-session D-009](../specs/issue-3515-spec-capture-during-session.md) | not built yet: parent issue #3515 is open. The instruction already says it. The CLI saves each pasted image ([issue-3569 D-001](../specs/issue-3569-pasted-image-pointers.md)) |

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P3: This overstates current coverage: pastedImageCaptures returns nil when a provider lacks PastedImageFinder, and only Claude and Codex implement it. Qualify the statement to those providers.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At docs/decisions/trace.md, line 39:

<comment>This overstates current coverage: `pastedImageCaptures` returns nil when a provider lacks `PastedImageFinder`, and only Claude and Codex implement it. Qualify the statement to those providers.</comment>

<file context>
@@ -31,12 +31,12 @@
 | How specs are found after session start | A short reminder at each user prompt | It keeps the agent as the decider and covers resumed sessions. Rejected: a general capture rule, and a hook that watches spec paths. | [issue-3515-spec-capture-during-session D-002](../specs/issue-3515-spec-capture-during-session.md) | not built yet: parent issue #3515 is open. The code already does it, with five cases (`trace_agent_hook.go`) |
 | Spec file limit | 25 files. Never drop a file that an earlier push recorded | Long sessions get more specs, and the oldest are the start sources. Rejected: keep the newest files. | [issue-3515-spec-capture-during-session D-005](../specs/issue-3515-spec-capture-during-session.md) | not built yet: parent issue #3515 is open. The code already does it (`spec.MaxEntries`) |
-| Pasted images (agent) | The agent does not capture a pasted image | A description is not the image. Rejected: a description of kind `image`. | [issue-3515-spec-capture-during-session D-009](../specs/issue-3515-spec-capture-during-session.md) | not built yet: parent issue #3515 is open. The instruction already says it. See Open conflicts |
+| Pasted images (agent) | The agent does not capture a pasted image | A description is not the image. Rejected: a description of kind `image`. | [issue-3515-spec-capture-during-session D-009](../specs/issue-3515-spec-capture-during-session.md) | not built yet: parent issue #3515 is open. The instruction already says it. The CLI saves each pasted image ([issue-3569 D-001](../specs/issue-3569-pasted-image-pointers.md)) |
 | How to record the purpose | A role field next to the kind | The kind is the format, the role is the purpose. Rejected: more kinds. | [issue-3531-spec-source-role D-001](../specs/issue-3531-spec-source-role.md) | verified: `Role` in the spec entry and the `chainloop.spec.role` annotation |
 | Role values | `task`, `spec`, `plan`, `reference` | They cover what a reviewer looks for. Rejected: only `spec`. | [issue-3531-spec-source-role D-002](../specs/issue-3531-spec-source-role.md) | verified: `ResolveSpecRole` drops other values |
</file context>
Suggested change
| Pasted images (agent) | The agent does not capture a pasted image | A description is not the image. Rejected: a description of kind `image`. | [issue-3515-spec-capture-during-session D-009](../specs/issue-3515-spec-capture-during-session.md) | not built yet: parent issue #3515 is open. The instruction already says it. The CLI saves each pasted image ([issue-3569 D-001](../specs/issue-3569-pasted-image-pointers.md)) |
| Pasted images (agent) | The agent does not capture a pasted image | A description is not the image. Rejected: a description of kind `image`. | [issue-3515-spec-capture-during-session D-009](../specs/issue-3515-spec-capture-during-session.md) | not built yet: parent issue #3515 is open. The instruction already says it. The CLI saves pasted images for Claude Code and Codex ([issue-3569 D-001](../specs/issue-3569-pasted-image-pointers.md)) |

Follow the Current Decisions format of brain chainloop-dev#148: each decision is a heading entry with Why, Rejected, Source, and Code lines.

Assisted-by: Claude Code
Signed-off-by: Miguel Martinez Trivino <miguel@chainloop.dev>

Chainloop-Trace-Sessions: 2fa80ea8-adee-42d4-8d71-2b2419570719

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

2 existing issues remain and 1 new issue found across 6 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="docs/decisions/authentication.md">

<violation number="1" location="docs/decisions/authentication.md:17">
P2: These entries omit the `- Rejected:` line that the commit's stated format requires, and the spec's recorded alternatives are dropped. Add a Rejected line to each entry, starting with Token delivery, using the spec's Alternatives considered.</violation>
</file>

Requires human review: Auto-approval blocked because this review re-detected 3 unresolved issues already reported by Cubic.

View guided diff | Re-trigger cubic

Comment thread docs/decisions/trace.md Outdated
Comment thread docs/decisions/service-endpoints.md

### Token delivery
A single-use handoff code that the client exchanges for the token.
- Why: It takes the token out of the URL.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2: These entries omit the - Rejected: line that the commit's stated format requires, and the spec's recorded alternatives are dropped. Add a Rejected line to each entry, starting with Token delivery, using the spec's Alternatives considered.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At docs/decisions/authentication.md, line 17:

<comment>These entries omit the `- Rejected:` line that the commit's stated format requires, and the spec's recorded alternatives are dropped. Add a Rejected line to each entry, starting with Token delivery, using the spec's Alternatives considered.</comment>

<file context>
@@ -12,14 +12,41 @@
-| Exchange endpoint | gRPC only, unauthenticated, with no HTTP mapping. Supersedes D-003 | No client needs a plain HTTP route, and the public surface stays smaller. | [issue-3626-login-code-exchange D-013](../specs/issue-3626-login-code-exchange.md) | verified: no `google.api.http` option on the RPC |
+### Token delivery
+A single-use handoff code that the client exchanges for the token.
+- Why: It takes the token out of the URL.
+- Source: [issue-3626-login-code-exchange D-001](../specs/issue-3626-login-code-exchange.md)
+- Code: verified: `ExchangeHandoff` in `internal/service/auth.go`
</file context>

…63 decisions

Assisted-by: Claude Code
Signed-off-by: Miguel Martinez Trivino <miguel@chainloop.dev>

Chainloop-Trace-Sessions: 2fa80ea8-adee-42d4-8d71-2b2419570719

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

1 existing issue remains and 1 new issue found across 3 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="docs/decisions/service-endpoints.md">

<violation number="1" location="docs/decisions/service-endpoints.md:103">
P2: The parent spec still lists CAS R-002/R-003 and F5/Traefik qualifications as open. Include that work before saying only D-007/D-004 remain or recommending `eng-spec --done`.</violation>
</file>

Requires human review: Auto-approval blocked because this review re-detected 2 unresolved issues already reported by Cubic.

View guided diff | Re-trigger cubic

Comment thread docs/decisions/service-endpoints.md Outdated

- **CAS transport.** [issue-3628-controlplane-http-dispatch D-003](../specs/issue-3628-controlplane-http-dispatch.md) keeps the CAS on separate endpoints. [issue-3628-single-endpoint D-020](../specs/issue-3628-single-endpoint.md) gives it a shared endpoint, and the code follows D-020 (#3663). Neither entry names the other. Proposed: supersede D-003 with a note that names D-020 in the next PR of issue #3628.
- **D-014 is not struck.** [issue-3628-single-endpoint D-020](../specs/issue-3628-single-endpoint.md) removes the separate-connection contract of [D-014](../specs/issue-3628-single-endpoint.md) for the CAS, in its text, but names only D-017, D-018, and D-019 as superseded. Proposed: mark D-014 superseded in the next PR of issue #3628.
- **Issue #3628 is open, but most of its decisions are in the code.** Only the deprecation steps (D-007) and the end of the two-Service chart layout (D-004) are left. Proposed: keep the issue open for these steps, or split them into a follow-up issue and run `eng-spec --done`.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2: The parent spec still lists CAS R-002/R-003 and F5/Traefik qualifications as open. Include that work before saying only D-007/D-004 remain or recommending eng-spec --done.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At docs/decisions/service-endpoints.md, line 103:

<comment>The parent spec still lists CAS R-002/R-003 and F5/Traefik qualifications as open. Include that work before saying only D-007/D-004 remain or recommending `eng-spec --done`.</comment>

<file context>
@@ -97,4 +98,6 @@ These entries were superseded inside their spec during the build. The parent iss
-- **CAS shared endpoint and CAS transport.** [issue-3628-single-endpoint D-020](../specs/issue-3628-single-endpoint.md) gives the CAS a shared endpoint with per-request dispatch. [issue-3628-controlplane-http-dispatch D-003](../specs/issue-3628-controlplane-http-dispatch.md) keeps the CAS on its native transport and separate endpoints. Neither entry names the other. Proposed: the owner says which one holds, in the spec of the CAS work.
+- **CAS transport.** [issue-3628-controlplane-http-dispatch D-003](../specs/issue-3628-controlplane-http-dispatch.md) keeps the CAS on separate endpoints. [issue-3628-single-endpoint D-020](../specs/issue-3628-single-endpoint.md) gives it a shared endpoint, and the code follows D-020 (#3663). Neither entry names the other. Proposed: supersede D-003 with a note that names D-020 in the next PR of issue #3628.
+- **D-014 is not struck.** [issue-3628-single-endpoint D-020](../specs/issue-3628-single-endpoint.md) removes the separate-connection contract of [D-014](../specs/issue-3628-single-endpoint.md) for the CAS, in its text, but names only D-017, D-018, and D-019 as superseded. Proposed: mark D-014 superseded in the next PR of issue #3628.
+- **Issue #3628 is open, but most of its decisions are in the code.** Only the deprecation steps (D-007) and the end of the two-Service chart layout (D-004) are left. Proposed: keep the issue open for these steps, or split them into a follow-up issue and run `eng-spec --done`.
</file context>
Suggested change
- **Issue #3628 is open, but most of its decisions are in the code.** Only the deprecation steps (D-007) and the end of the two-Service chart layout (D-004) are left. Proposed: keep the issue open for these steps, or split them into a follow-up issue and run `eng-spec --done`.
- **Issue #3628 is open, but most of its decisions are in the code.** D-007 and the end of the two-Service chart layout in D-004 remain, and the CAS R-002/R-003 and F5/Traefik qualifications are still open. Proposed: keep the issue open until these are resolved, or move them to a follow-up issue.

State the code state once per entry, and keep the open-issue state in Open conflicts. Correct the entries where the code differs from the page.

Assisted-by: Claude Code
Signed-off-by: Miguel Martinez Trivino <miguel@chainloop.dev>

Chainloop-Trace-Sessions: 2fa80ea8-adee-42d4-8d71-2b2419570719

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

4 issues found across 6 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="docs/decisions/authentication.md">

<violation number="1" location="docs/decisions/authentication.md:59">
P2: This page is marked as generated and says not to edit it by hand, but these lines were hand-written. Regenerate the page with `eng-spec --decisions` so the drift and conflict text comes from the tool, or record the code change in a spec as the Open conflicts entry proposes.</violation>
</file>

<file name="docs/decisions/attestation-cli.md">

<violation number="1" location="docs/decisions/attestation-cli.md:20">
P2: `attestation verify` is not in `repositoryOrganizationCommands`, so it never reads `organization` from `.chainloop.yml`. Narrow this line to the five commands that do (`init`, `add`, `push`, `status`, `reset`), or mark the rest as drift.</violation>
</file>

<file name="docs/decisions/service-endpoints.md">

<violation number="1" location="docs/decisions/service-endpoints.md:36">
P3: The “no second Ingress” clause also appears to apply to the control plane, but D-002 keeps the legacy gRPC ingress independent. Scope that clause to the CAS shared endpoint and state that the control-plane legacy ingress remains.</violation>
</file>

<file name="docs/decisions/artifact-cas.md">

<violation number="1" location="docs/decisions/artifact-cas.md:85">
P2: The code does not retry every existence-check error or drop the client for every upload-path error: it retries only a failed cached client, and drops the client only on a backend `Upload` failure. Narrow these claims to match the actual branches.</violation>
</file>

Reply with feedback, questions, or to request a fix.

View guided diff | Re-trigger cubic


## Open conflicts

- **Browser download login.** [issue-3626 D-008](../specs/issue-3626-login-code-exchange.md) keeps the download flow on the legacy callback. The code moved it to the handoff code exchange (`app/controlplane/internal/service/casredirect.go`). The legacy switch does not bring it back, and the download token stays short-lived. Proposed: write a spec that records the change. The decision expected "a separate change" for it.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2: This page is marked as generated and says not to edit it by hand, but these lines were hand-written. Regenerate the page with eng-spec --decisions so the drift and conflict text comes from the tool, or record the code change in a spec as the Open conflicts entry proposes.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At docs/decisions/authentication.md, line 59:

<comment>This page is marked as generated and says not to edit it by hand, but these lines were hand-written. Regenerate the page with `eng-spec --decisions` so the drift and conflict text comes from the tool, or record the code change in a spec as the Open conflicts entry proposes.</comment>

<file context>
@@ -56,4 +56,4 @@ Not shown: 6 smaller decisions of [issue-3626-login-code-exchange](../specs/issu
 ## Open conflicts
 
-- **Browser download login.** [issue-3626 D-008](../specs/issue-3626-login-code-exchange.md) keeps the download flow on the legacy callback. The code moved it to the handoff code exchange (`app/controlplane/internal/service/casredirect.go`). Proposed: write a spec that records the change. The decision expected "a separate change" for it.
+- **Browser download login.** [issue-3626 D-008](../specs/issue-3626-login-code-exchange.md) keeps the download flow on the legacy callback. The code moved it to the handoff code exchange (`app/controlplane/internal/service/casredirect.go`). The legacy switch does not bring it back, and the download token stays short-lived. Proposed: write a spec that records the change. The decision expected "a separate change" for it.
</file context>

- Why: `chainloop trace init` already writes these keys.
- Rejected: a new `project` key.
- Source: [issue-3063-attestation-repo-config D-001](../specs/issue-3063-attestation-repo-config.md)
- Code: verified (#3502, #3517, #3518): attestation commands read `organization`, and `attestation init` reads `projectName` (`app/cli/internal/repositoryconfig/config.go`, `app/cli/cmd/attestation.go`)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2: attestation verify is not in repositoryOrganizationCommands, so it never reads organization from .chainloop.yml. Narrow this line to the five commands that do (init, add, push, status, reset), or mark the rest as drift.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At docs/decisions/attestation-cli.md, line 20:

<comment>`attestation verify` is not in `repositoryOrganizationCommands`, so it never reads `organization` from `.chainloop.yml`. Narrow this line to the five commands that do (`init`, `add`, `push`, `status`, `reset`), or mark the rest as drift.</comment>

<file context>
@@ -17,28 +17,28 @@
 - Rejected: a new `project` key.
 - Source: [issue-3063-attestation-repo-config D-001](../specs/issue-3063-attestation-repo-config.md)
-- Code: not built yet: issue #3063 is open; the code already does it (#3502, #3517, #3518). Attestation commands read `organization`, and `attestation init` reads `projectName` (`app/cli/internal/repositoryconfig/config.go`, `app/cli/cmd/attestation.go`)
+- Code: verified (#3502, #3517, #3518): attestation commands read `organization`, and `attestation init` reads `projectName` (`app/cli/internal/repositoryconfig/config.go`, `app/cli/cmd/attestation.go`)
 
 ### Order for the organization
</file context>
Suggested change
- Code: verified (#3502, #3517, #3518): attestation commands read `organization`, and `attestation init` reads `projectName` (`app/cli/internal/repositoryconfig/config.go`, `app/cli/cmd/attestation.go`)
- Code: verified (#3502, #3517, #3518): `add`, `init`, `push`, `reset`, and `status` read `organization`, and `attestation init` reads `projectName` (`app/cli/internal/repositoryconfig/config.go`, `app/cli/cmd/attestation.go`); `attestation verify` does not

## Open conflicts

- **Existence entry lifetime is not configurable.** [issue-3543 D-007](../specs/issue-3543-cas-existence-cache.md) says 24 hours, configurable. The code has a 24-hour constant and no setting (`pkg/cache/casexistence/casexistence.go`). The off switch that R-004 asks for is also missing: the CAS always turns the cache on (`app/artifact-cas/cmd/wire.go`). Proposed: fix the code.
- **Client cache reload trigger.** [issue-3543 D-009](../specs/issue-3543-cas-existence-cache.md) reloads a client once on an authentication error. The code reloads once on any existence-check error, and drops the cached client on any upload error, with no retry (`app/artifact-cas/internal/service/bytestream.go`). Proposed: the owner decides between a code fix and a spec.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2: The code does not retry every existence-check error or drop the client for every upload-path error: it retries only a failed cached client, and drops the client only on a backend Upload failure. Narrow these claims to match the actual branches.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At docs/decisions/artifact-cas.md, line 85:

<comment>The code does not retry every existence-check error or drop the client for every upload-path error: it retries only a failed cached client, and drops the client only on a backend `Upload` failure. Narrow these claims to match the actual branches.</comment>

<file context>
@@ -81,5 +81,5 @@ None.
-- **Existence entry lifetime is not configurable.** [issue-3543 D-007](../specs/issue-3543-cas-existence-cache.md) says 24 hours, configurable. The code has a 24-hour constant and no setting (`pkg/cache/casexistence/casexistence.go`). Proposed: fix the code.
-- **Client cache reload trigger.** [issue-3543 D-009](../specs/issue-3543-cas-existence-cache.md) reloads a client once on an authentication error. The code reloads once on any existence-check error (`app/artifact-cas/internal/service/bytestream.go`). Proposed: the owner decides between a code fix and a spec.
+- **Existence entry lifetime is not configurable.** [issue-3543 D-007](../specs/issue-3543-cas-existence-cache.md) says 24 hours, configurable. The code has a 24-hour constant and no setting (`pkg/cache/casexistence/casexistence.go`). The off switch that R-004 asks for is also missing: the CAS always turns the cache on (`app/artifact-cas/cmd/wire.go`). Proposed: fix the code.
+- **Client cache reload trigger.** [issue-3543 D-009](../specs/issue-3543-cas-existence-cache.md) reloads a client once on an authentication error. The code reloads once on any existence-check error, and drops the cached client on any upload error, with no retry (`app/artifact-cas/internal/service/bytestream.go`). Proposed: the owner decides between a code fix and a spec.
</file context>
Suggested change
- **Client cache reload trigger.** [issue-3543 D-009](../specs/issue-3543-cas-existence-cache.md) reloads a client once on an authentication error. The code reloads once on any existence-check error, and drops the cached client on any upload error, with no retry (`app/artifact-cas/internal/service/bytestream.go`). Proposed: the owner decides between a code fix and a spec.
- **Client cache reload trigger.** [issue-3543 D-009](../specs/issue-3543-cas-existence-cache.md) specifies one reload on an authentication error. The code retries an existence check once only when the failed client was cached, regardless of error type, and drops the cached client on backend `Upload` failures without retrying the upload (`app/artifact-cas/internal/service/bytestream.go`). Proposed: the owner decides between a code fix and a spec.

- Code: not built yet: the single port shipped on 2026-10-19, so the first step is not due. No release note announces the dates yet

### Ingress shape
One Service and one hostname per service. Two Ingress objects on one host only where the controller needs it. Replaced, for the control plane, by [issue-3628-controlplane-http-dispatch D-002](../specs/issue-3628-controlplane-http-dispatch.md), and for the CAS by [issue-3628-single-endpoint D-020](../specs/issue-3628-single-endpoint.md): one catch-all Ingress with HTTP/2 upstream, and no second Ingress.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P3: The “no second Ingress” clause also appears to apply to the control plane, but D-002 keeps the legacy gRPC ingress independent. Scope that clause to the CAS shared endpoint and state that the control-plane legacy ingress remains.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At docs/decisions/service-endpoints.md, line 36:

<comment>The “no second Ingress” clause also appears to apply to the control plane, but D-002 keeps the legacy gRPC ingress independent. Scope that clause to the CAS shared endpoint and state that the control-plane legacy ingress remains.</comment>

<file context>
@@ -12,92 +12,95 @@
 
 ### Ingress shape
-One Service and one hostname per service. Two Ingress objects on one host only where the controller needs it. Partly replaced, for the control plane, by [issue-3628-controlplane-http-dispatch D-002](../specs/issue-3628-controlplane-http-dispatch.md): one ingress path with HTTP/2 upstream.
+One Service and one hostname per service. Two Ingress objects on one host only where the controller needs it. Replaced, for the control plane, by [issue-3628-controlplane-http-dispatch D-002](../specs/issue-3628-controlplane-http-dispatch.md), and for the CAS by [issue-3628-single-endpoint D-020](../specs/issue-3628-single-endpoint.md): one catch-all Ingress with HTTP/2 upstream, and no second Ingress.
 - Why: nginx sets the backend protocol per Ingress object, so one object cannot carry both protocols.
 - Source: [issue-3628-single-endpoint D-004](../specs/issue-3628-single-endpoint.md)
</file context>
Suggested change
One Service and one hostname per service. Two Ingress objects on one host only where the controller needs it. Replaced, for the control plane, by [issue-3628-controlplane-http-dispatch D-002](../specs/issue-3628-controlplane-http-dispatch.md), and for the CAS by [issue-3628-single-endpoint D-020](../specs/issue-3628-single-endpoint.md): one catch-all Ingress with HTTP/2 upstream, and no second Ingress.
One Service and one hostname per service. Two Ingress objects on one host only where the controller needs it. For the control plane, [issue-3628-controlplane-http-dispatch D-002](../specs/issue-3628-controlplane-http-dispatch.md) specifies one catch-all shared-endpoint Ingress with HTTP/2 upstream, while the legacy gRPC ingress remains independent. For the CAS, [issue-3628-single-endpoint D-020](../specs/issue-3628-single-endpoint.md) specifies one catch-all shared-endpoint Ingress with HTTP/2 upstream and no split Ingress.

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.

1 participant