Skip to content

feat(mint)!: harden repos scope against cross-repo minting - #5826

Merged
ifireball merged 14 commits into
fullsend-ai:mainfrom
ifireball:harden-mint-repos-scope
Aug 3, 2026
Merged

feat(mint)!: harden repos scope against cross-repo minting#5826
ifireball merged 14 commits into
fullsend-ai:mainfrom
ifireball:harden-mint-repos-scope

Conversation

@ifireball

@ifireball ifireball commented Aug 2, 2026

Copy link
Copy Markdown
Member

Summary

  • Tighten mint repos authorization: same-org mints default to the requesting repo only; foreign (cross-org) mints require empty repos (with ["*"] as an empty alias). Org-mode shapes stay available only when PER_ORG_FOREIGN_COMPAT is enabled (ADR 0077).
  • When mint deploy uses an on-disk checkout and the CLI commit is still unset/dev, stamp the mint with git HEAD from that source and surface Version/Commit in the deploy summary.
  • Expose effective PER_ORG_FOREIGN_COMPAT on GET /v1/status (per_org_foreign_compat) and print it from traffic env in fullsend mint status (missing → off, compatible with older mints).

Fixes #5828
Fixes #5829

Accepted ADR edits

  • ADR 0060: annotation only — points the old same-org installation-wide / unrestricted-repos consequences at ADR 0077. FOREIGN allowlists and target_org are unchanged.

Test plan

  • Unit: go test in internal/mintcore, internal/cli, internal/dispatch/gcf (repos scope, status field, deploy-commit resolution, mint status on/off, embedded zip file count)
  • Confirm embeds under internal/dispatch/gcf/mintsrc/mintcore/ match internal/mintcore/
  • After deploy with PER_ORG_FOREIGN_COMPAT=true: same-org org-mode / .fullsend shapes still mint; without the flag, same-org broad lists and install-wide are denied as expected
  • fullsend mint status shows Per-org foreign compat: on|off matching traffic env
  • Dry-run / real deploy from a checkout stamps commit from checkout when CLI commit is dev
  • CI e2e / behaviour jobs on this PR (CLI changes are covered by unit tests; full make e2e-test runs in the PR e2e workflow)

BREAKING CHANGE: same-org mint requests that previously used installation-wide or broad org-mode repos lists are denied unless PER_ORG_FOREIGN_COMPAT is enabled (and still never allow same-org installation-wide tokens). Foreign mints must use empty repos.

ifireball and others added 4 commits July 29, 2026 14:13
Restrict same-org mints to the requesting repo by default, allow only
empty repos on foreign mints, and gate org-mode exceptions behind
PER_ORG_FOREIGN_COMPAT so workflows keep working when enabled.

Signed-off-by: Barak Korren <bkorren@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
When mint deploy uses on-disk source and CLI commitSHA is still unset,
stamp git HEAD into the mint and show Version/Commit in the summary.

Signed-off-by: Barak Korren <bkorren@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Expose PER_ORG_FOREIGN_COMPAT on GET /v1/status and print it from
traffic env in fullsend mint status (absent = off for older mints).

Signed-off-by: Barak Korren <bkorren@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Capture the PER_ORG_FOREIGN_COMPAT repos policy as an accepted ADR and
point ADR 0060 / architecture.md at it.

Signed-off-by: Barak Korren <bkorren@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@ifireball
ifireball requested a review from a team as a code owner August 2, 2026 08:59
@fullsend-ai-review

fullsend-ai-review Bot commented Aug 2, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 8:59 AM UTC · Completed 9:18 AM UTC
Commit: d7d444c · View workflow run →

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Harden mint repos scoping to prevent cross-repo minting

✨ Enhancement 🐞 Bug fix 🧪 Tests 📝 Documentation ⚙️ Configuration changes 🕐 40+ Minutes

Grey Divider

AI Description

• Enforce least-privilege repos scoping: same-org defaults to requesting repo; foreign requires
 empty repos.
• Gate legacy org-mode shapes behind PER_ORG_FOREIGN_COMPAT and expose it via /v1/status + CLI
 status.
• Stamp deploy commit from local checkout git HEAD when CLI commit is unset/dev, and show it in
 deploy summary.
Diagram

graph TD
  W(["Workflow (OIDC)"]) --> H["Mint handler"] --> V["Repos scope validator"]
  H --> GH{{"GitHub API"}}
  H --> S["GET /v1/status"]
  C["CLI mint deploy"] --> R["Resolve commit"] --> G{{"git HEAD"}}
  C --> P["Deploy (GCF/CF)"]

  subgraph Legend
    direction LR
    _act(["Caller"]) ~~~ _svc["Service/module"] ~~~ _ext{{"External"}}
  end
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Remove `repos` input for same-org mints
  • ➕ Eliminates an entire class of same-org scope escalation; scope is always derived from OIDC claims.
  • ➕ Simplifies policy surface area (no compat exceptions needed for most callers).
  • ➖ Breaks org-mode dispatch workflows that legitimately need {self,.fullsend} or broader lists.
  • ➖ Requires a separate mechanism/endpoint for .fullsend-style orchestration.
2. Per-org allowlist instead of global `PER_ORG_FOREIGN_COMPAT`
  • ➕ More granular than a single flag; reduces risk of enabling compat broadly.
  • ➕ Lets operators explicitly enumerate permitted same-org shapes per org.
  • ➖ More operational/config complexity; needs new config distribution and validation.
  • ➖ Harder to communicate and debug than a single effective boolean surfaced in status.
3. Allow cross-org non-empty repos with stricter validation
  • ➕ Could preserve prior foreign behavior while tightening same-org.
  • ➕ Potentially avoids forcing installation-wide tokens for cross-org use cases.
  • ➖ Complex to correctly validate requested repos against FOREIGN allowlists without reintroducing confused-deputy risks.
  • ➖ Larger policy surface area and higher audit burden than “foreign must be empty”.

Recommendation: The chosen approach (requesting-repo-only by default, foreign requires empty repos, and narrowly-scoped compat exceptions behind PER_ORG_FOREIGN_COMPAT) is the best balance of least privilege and operational continuity. Keeping the compat flag explicit and surfacing its effective value in /v1/status and CLI status reduces rollout/debug risk while still closing the core cross-repo minting vector.

Files changed (21) +879 / -77

Enhancement (4) +152 / -19
mint.goShow PER_ORG_FOREIGN_COMPAT in status and stamp commit in deploy summaries +32/-2

Show PER_ORG_FOREIGN_COMPAT in status and stamp commit in deploy summaries

• Adds a helper to render 'PER_ORG_FOREIGN_COMPAT' from traffic env as on/off (missing treated as off for older mints). Uses 'resolveMintDeployCommit' for both GCF and Cloudflare deploys, prints when resolved, and includes Version/Commit in deploy summaries; prints compat state in 'mint status'.

internal/cli/mint.go

config.goAdd WorkerConfig field for PER_ORG_FOREIGN_COMPAT propagation +11/-1

Add WorkerConfig field for PER_ORG_FOREIGN_COMPAT propagation

• Extends mintcore 'WorkerConfig' with 'PerOrgForeignCompat' and updates 'ParseWorkerConfig' to set 'h.perOrgForeignCompat' via 'envTruthy'. Enables non-env-based configuration (e.g., worker config) to drive compat behavior.

internal/mintcore/config.go

handler.goEnforce hardened repos scope and report compat state in status +30/-16

Enforce hardened repos scope and report compat state in status

• Adds 'PerOrgForeignCompat' to status response JSON and stores an internal 'perOrgForeignCompat' flag (defaulted from env). Normalizes 'repos' (supporting '['*']' → empty) and calls 'validateReposScope' before allowing same-org or cross-org minting.

internal/mintcore/handler.go

repos_scope.goCentralize repos normalization and scope validation rules +79/-0

Centralize repos normalization and scope validation rules

• Adds helpers to normalize 'repos' ('['*']' alias), parse truthy compat flags, and enforce the hardened policy: foreign must be empty; same-org must be exactly the requesting repo unless compat unlocks limited org-mode shapes.

internal/mintcore/repos_scope.go

Bug fix (1) +43 / -0
deploy_identity.goResolve deploy commit SHA from local checkout HEAD +43/-0

Resolve deploy commit SHA from local checkout HEAD

• Adds 'resolveMintDeployCommit' to preserve explicit commits but, when deploying from an on-disk source directory with 'dev'/empty commit, runs 'git -C <dir> rev-parse HEAD' to stamp a concrete SHA. Avoids invoking git for embedded/missing source dirs.

internal/cli/deploy_identity.go

Tests (7) +495 / -37
deploy_identity_test.goUnit tests for deploy-commit resolution logic +87/-0

Unit tests for deploy-commit resolution logic

• Covers preserving non-dev commits, missing source directories, non-git directories, and resolving a full 40-char SHA from a temporary git repo. Ensures both 'dev' and empty commit inputs resolve when a checkout exists.

internal/cli/deploy_identity_test.go

mint_test.goTests for compat-label rendering and mint status output +59/-0

Tests for compat-label rendering and mint status output

• Adds unit tests for 'perOrgForeignCompatLabel' truthy parsing. Extends mint status tests to assert the compat line is printed and toggles to 'on' when traffic env sets 'PER_ORG_FOREIGN_COMPAT=true'.

internal/cli/mint_test.go

provisioner_test.goVerify embedded bundle contains repos_scope.go +1/-0

Verify embedded bundle contains repos_scope.go

• Extends the bundle test to assert 'mintcore/repos_scope.go' is included in the embedded mint source output.

internal/dispatch/gcf/provisioner_test.go

config_test.goEnable compat in full mint flow config test +1/-0

Enable compat in full mint flow config test

• Adjusts the full mint flow test to explicitly set 'h.perOrgForeignCompat = true' so the test request shape remains valid under the hardened repos policy.

internal/mintcore/config_test.go

handler_test.goExpand handler tests for repos hardening, star alias, and status field +248/-37

Expand handler tests for repos hardening, star alias, and status field

• Adds coverage for 'per_org_foreign_compat' always being present in status (including explicit false), denies same-org empty repos even with compat on, allows cross-org empty repos (and '['*']' alias), and denies cross-org non-empty repos. Updates various existing tests to use requesting-repo repos lists consistent with new enforcement.

internal/mintcore/handler_test.go

repos_scope_test.goUnit tests for normalization, truthy parsing, and scope validation matrix +98/-0

Unit tests for normalization, truthy parsing, and scope validation matrix

• Adds a table-driven test suite covering '['*']' normalization, 'envTruthy' inputs, and allowed/denied combinations for foreign vs same-org and compat on/off (including '.fullsend' caller behavior).

internal/mintcore/repos_scope_test.go

testmain_test.goDefault PER_ORG_FOREIGN_COMPAT on in tests +1/-0

Default PER_ORG_FOREIGN_COMPAT on in tests

• Sets 'PER_ORG_FOREIGN_COMPAT=true' in the shared test defaults to keep existing org-mode test shapes working unless explicitly overridden per test.

internal/mintcore/testmain_test.go

Documentation (5) +67 / -3
0060-cross-org-mint-authorization-via-org-variables.mdAdd note pointing to new repos-scope hardening ADR +7/-0

Add note pointing to new repos-scope hardening ADR

• Documents that prior ADR 0060 defaults around installation-wide/same-org repo lists are superseded for 'repos' scoping. Links readers to ADR 0077 for the current policy while clarifying that FOREIGN allowlists/'target_org' remain unchanged.

docs/ADRs/0060-cross-org-mint-authorization-via-org-variables.md

0077-mint-repos-scope-hardening.mdNew ADR defining hardened repos scoping and compat flag behavior +54/-0

New ADR defining hardened repos scoping and compat flag behavior

• Introduces ADR 0077 describing the threat model motivation, normalization of '['*']' to empty, foreign=empty-only rule, same-org=requesting-repo-only rule, and the limited 'PER_ORG_FOREIGN_COMPAT' exceptions. Defines required observability via '/v1/status' and CLI output.

docs/ADRs/0077-mint-repos-scope-hardening.md

architecture.mdUpdate mint authorization docs to reflect hardened repos policy +2/-1

Update mint authorization docs to reflect hardened repos policy

• Adjusts the architecture overview to remove the old “empty repos is installation-wide on either path” description. Adds a dedicated bullet summarizing the new same-org vs foreign repos policy and the 'PER_ORG_FOREIGN_COMPAT' exceptions.

docs/architecture.md

infrastructure-reference.mdDocument 'per_org_foreign_compat' in '/v1/status' response +2/-1

Document 'per_org_foreign_compat' in '/v1/status' response

• Updates the status endpoint example JSON to include 'per_org_foreign_compat'. Clarifies that the field is always present and defaults to 'false' when unset.

docs/guides/infrastructure/infrastructure-reference.md

standalone-mint.mdDocument PER_ORG_FOREIGN_COMPAT and status field behavior +2/-1

Document PER_ORG_FOREIGN_COMPAT and status field behavior

• Adds 'PER_ORG_FOREIGN_COMPAT' to the standalone mint env var reference, describing the allowed org-mode shapes and the default-off behavior. Updates proxy behavior docs to note that '/v1/status' returns 'per_org_foreign_compat' with default 'false' when unset.

docs/guides/infrastructure/standalone-mint.md

Other (4) +122 / -18
config.go.embedPlumb PerOrgForeignCompat through embedded mint worker config +11/-1

Plumb PerOrgForeignCompat through embedded mint worker config

• Extends embedded 'WorkerConfig' with 'PerOrgForeignCompat' and ensures 'ParseWorkerConfig' sets the handler’s 'perOrgForeignCompat' using the shared truthy parsing. Keeps embedded mint behavior aligned with 'internal/mintcore'.

internal/dispatch/gcf/mintsrc/mintcore/config.go.embed

handler.go.embedApply repos-scope validation and expose compat flag in embedded status +30/-16

Apply repos-scope validation and expose compat flag in embedded status

• Adds 'per_org_foreign_compat' to '/v1/status' responses and stores 'perOrgForeignCompat' on the handler. Normalizes 'repos' (including '['*']' alias) and enforces same-org vs foreign repos scoping before minting tokens.

internal/dispatch/gcf/mintsrc/mintcore/handler.go.embed

repos_scope.go.embedAdd embedded repos-scope enforcement utilities +79/-0

Add embedded repos-scope enforcement utilities

• Introduces embedded implementations of 'normalizeMintRepos', 'envTruthy', and 'validateReposScope' for the bundled GCF mint source. Mirrors the main mintcore logic to avoid behavior drift between deployment modes.

internal/dispatch/gcf/mintsrc/mintcore/repos_scope.go.embed

provisioner.goInclude repos_scope.go in embedded mint source bundle +2/-1

Include repos_scope.go in embedded mint source bundle

• Updates the go:embed list and embedded file mapping to ship 'mintcore/repos_scope.go' in the bundled mint source. Ensures deployed embedded mint includes the hardened repos policy.

internal/dispatch/gcf/provisioner.go

@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown

Site preview

Preview: https://60c0ccef-site.fullsend-ai.workers.dev

Commit: fb8dd189586bbc311019a61b32985dde6bec1ed6

@qodo-code-review

qodo-code-review Bot commented Aug 2, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (1) 📜 Skill insights (1)

Context used
✅ Compliance rules (platform): 54 rules

Grey Divider


Action required

1. Worker compat flag dropped ✓ Resolved 🐞 Bug ≡ Correctness
Description
Cloudflare Worker (WASM) deployments cannot enable PER_ORG_FOREIGN_COMPAT because the Worker adapter
never serializes WorkerConfig.PerOrgForeignCompat into configJSON, so ParseWorkerConfig always sets
perOrgForeignCompat=false. This will incorrectly deny org-mode repos shapes on CF even when
operators set the flag in Worker env.
Code

internal/mintcore/config.go[R92-93]

+	h.perOrgForeignCompat = envTruthy(cfg.PerOrgForeignCompat)
+	return h, nil
Relevance

●●● Strong

Concrete config-plumbing bug; precedent for fixing Worker config/env wiring omissions.

PR-#5615

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
ParseWorkerConfig enables compat solely from the WorkerConfig field added in this PR, but the
Cloudflare Worker adapter’s config JSON builder omits that field; therefore cfg.PerOrgForeignCompat
remains empty and envTruthy disables compat on Workers.

internal/mintcore/config.go[41-50]
internal/mintcore/config.go[88-93]
cmd/mint-wasm/main.go[51-86]
internal/dispatch/cf/workersrc/src/index.ts[51-73]
internal/dispatch/cf/workersrc/src/index.ts[158-173]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Cloudflare Worker deployments build a JSON object (mintcore.WorkerConfig) and pass it into cmd/mint-wasm, which then calls mintcore.ParseWorkerConfig. This PR adds WorkerConfig.PerOrgForeignCompat and ParseWorkerConfig reads it to enable compat behavior, but the CF Worker adapter does not include the field in the JSON, making the flag impossible to enable on CF.

## Issue Context
- ParseWorkerConfig now sets `h.perOrgForeignCompat` from `cfg.PerOrgForeignCompat`.
- The CF adapter’s `buildWasmConfig` must include a `PerOrgForeignCompat` property (PascalCase) sourced from Worker env (e.g. `env.PER_ORG_FOREIGN_COMPAT`).

## Fix Focus Areas
- internal/mintcore/config.go[47-93]
- cmd/mint-wasm/main.go[51-86]
- internal/dispatch/cf/workersrc/src/index.ts[51-73]
- internal/dispatch/cf/workersrc/src/index.ts[158-173]

## Suggested change
1. In `internal/dispatch/cf/workersrc/src/index.ts`:
  - Extend `Env` to optionally include `PER_ORG_FOREIGN_COMPAT?: string`.
  - Add `PerOrgForeignCompat: env.PER_ORG_FOREIGN_COMPAT ?? ""` to the object returned by `buildWasmConfig`.
2. Add a small unit/integration test (TS or Go-side) that asserts the generated configJSON includes `PerOrgForeignCompat` when the env var is set, so this doesn’t regress.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. ADR 0060 edit unmentioned 📘 Rule violation § Compliance
Description
This PR modifies an already Accepted ADR (docs/ADRs/0060-...) but the PR description does not
explicitly call out that ADR and summarize the change. This reduces auditability and violates the
requirement to mention accepted ADR edits in the PR description.
Code

docs/ADRs/0060-cross-org-mint-authorization-via-org-variables.md[R87-90]

+## Later note (repos scope hardening)
+
+Same-org installation-wide tokens and unrestricted `repos` lists are no longer the default.
+`repos` authorization is decided in
Relevance

●●● Strong

Team closely polices changes to Accepted ADRs; adding explicit PR-description callout is low-effort
compliance.

PR-#5244

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
docs/ADRs/0060-... is marked status: Accepted / ## Status: Accepted, and this PR adds a new
note section referencing ADR 0077. The checklist requires PR descriptions to explicitly mention any
modified Accepted ADRs, but the provided PR description only references ADR 0077 and does not call
out ADR 0060.

Rule 1062059: Call out edits to accepted ADRs in PR descriptions
docs/ADRs/0060-cross-org-mint-authorization-via-org-variables.md[1-21]
docs/ADRs/0060-cross-org-mint-authorization-via-org-variables.md[87-92]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The PR edits an Accepted ADR (`ADR 0060`) but the PR description does not explicitly mention it.

## Issue Context
Compliance requires that edits to Accepted ADRs be called out in the PR description with the ADR identifier/filename and a brief summary of what changed.

## Fix Focus Areas
- docs/ADRs/0060-cross-org-mint-authorization-via-org-variables.md[87-92]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Commit resolution unreported ✓ Resolved 🐞 Bug ◔ Observability
Description
When git rev-parse fails during mint deploy, resolveMintDeployCommit silently falls back to the
original commit value and the deploy flow emits no warning. This can leave the deploy summary
stamped as "dev"/empty without indicating that checkout-based commit resolution failed.
Code

internal/cli/deploy_identity.go[R26-28]

+	sha, err := gitRevParse(sourceDir, "HEAD")
+	if err != nil || sha == "" {
+		return commit
Relevance

●● Moderate

Repo often prefers visibility for dropped behavior, but adding warnings here is subjective without
direct precedent.

PR-#1040

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The new helper returns the original commit when gitRevParse errors, and the deploy flow only logs on
successful resolution while always printing whatever commit it ended up with in the summary.

internal/cli/deploy_identity.go[15-30]
internal/cli/deploy_identity.go[33-41]
internal/cli/mint.go[533-540]
internal/cli/mint.go[588-594]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`resolveMintDeployCommit` swallows errors from `gitRevParse` and the deploy command only prints a message when resolution succeeds. When resolution fails (not a git repo, git missing, etc.), the summary can still display `Commit: dev`/empty with no diagnostic.

## Issue Context
The intent of this PR is to improve deploy traceability by stamping a real commit when deploying from a checkout. Silent fallback reduces the value of that feature.

## Fix Focus Areas
- internal/cli/deploy_identity.go[15-43]
- internal/cli/mint.go[533-555]
- internal/cli/mint.go[588-594]

## Suggested change
- Keep the non-fatal behavior, but surface the failure:
 - Option A: change `resolveMintDeployCommit` to return `(string, error)` and have callers print `printer.StepInfo/StepWarn` when commit is still `dev`/empty and git resolution errored (include the error, and ideally stderr).
 - Option B: keep signature but log a warning inside `resolveMintDeployCommit` when `os.Stat(sourceDir)` succeeds yet `gitRevParse` fails.
- Consider including captured stderr in the returned error for better diagnostics.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


4. No e2e-test evidence for cli ✗ Dismissed 📘 Rule violation ▣ Testability
Description
Files under internal/cli/ are modified, but there is no evidence in the PR description (or CI info
provided) that make e2e-test was executed and passed. This risks regressions in a critical
internal module path.
Code

internal/cli/deploy_identity.go[R10-15]

+// resolveMintDeployCommit returns the commit to stamp into a mint deploy.
+// When commit is already set to something other than "dev"/empty, it is
+// returned unchanged. When deploying from on-disk source (sourceDir exists)
+// and commit is unset, it tries git -C sourceDir rev-parse HEAD. Embedded
+// deploys (missing sourceDir) never invoke git.
+func resolveMintDeployCommit(commit, sourceDir string) string {
Relevance

●● Moderate

Process/test-evidence requirement plausible but unclear if enforced via PR description vs CI; no
close precedents.

PR-#2277

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The diff adds/changes code under internal/cli/, which triggers the e2e-test requirement for
critical internal modules. With no CI status included and no explicit statement in the PR
description that make e2e-test passed, the rule is not satisfied.

Rule 1062051: Run end-to-end tests for critical internal modules before merge
internal/cli/deploy_identity.go[1-43]
internal/cli/mint.go[521-600]
internal/cli/mint.go[1518-1522]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Changes under `internal/cli/` require running end-to-end tests (`make e2e-test`) before merge, but the PR description does not state they were run and no CI evidence is provided.

## Issue Context
This rule applies whenever `internal/cli/` is modified.

## Fix Focus Areas
- internal/cli/deploy_identity.go[1-43]
- internal/cli/mint.go[520-595]
- internal/cli/mint.go[1518-1522]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Informational

5. Guide not in admin/user 📜 Skill insight ⌂ Architecture
Description
This PR modifies guide documentation under docs/guides/ that is not placed within the required
docs/guides/admin/ or docs/guides/user/ subdirectories, violating the guide directory structure
convention. This can confuse audience segmentation and breaks the documentation organization
standard.
Code

docs/guides/infrastructure/standalone-mint.md[119]

+| `PER_ORG_FOREIGN_COMPAT` | When `1`/`true`/`yes`, allow org-mode `repos` shapes: any non-empty list from `.fullsend` callers; `[.fullsend]` or `{self,.fullsend}` from enrolled callers. Default off (same-org = requesting repo only). Does not allow same-org installation-wide tokens. | `true` |
Relevance

● Weak

Very similar “move guide into admin/user” requests were rejected; repo keeps dev/infrastructure
guides in place.

PR-#5454
PR-#4901

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The cited modified guides are located under docs/guides/infrastructure/..., which is a direct
subpath of docs/guides/ but not one of the sanctioned guide locations (docs/guides/admin/ or
docs/guides/user/), demonstrating that the PR updates guides outside the required directory
structure.

docs/guides/infrastructure/standalone-mint.md[1-8]
docs/guides/infrastructure/infrastructure-reference.md[1-5]
Skill: writing-user-docs

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The PR modifies guide files under `docs/guides/infrastructure/`, but guides must be placed under either `docs/guides/admin/` or `docs/guides/user/` to comply with the required guide directory structure.

## Issue Context
Because these files are being updated in this PR, they need to be relocated (and any internal references adjusted as needed) so the documentation remains organized according to the admin/user audience segmentation convention.

## Fix Focus Areas
- docs/guides/infrastructure/standalone-mint.md[1-220]
- docs/guides/infrastructure/infrastructure-reference.md[1-220]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

To customize comments, go to the Qodo configuration screen, or learn more in the docs.

Qodo Logo

Comment thread docs/ADRs/0060-cross-org-mint-authorization-via-org-variables.md
Comment thread internal/cli/deploy_identity.go Outdated
Comment thread internal/mintcore/config.go Outdated
Comment thread internal/cli/deploy_identity.go Outdated
@fullsend-ai-review

fullsend-ai-review Bot commented Aug 2, 2026

Copy link
Copy Markdown

Review

Findings

Medium

  • [stale-documentation] docs/guides/infrastructure/mint-administration.md:378 — The "Minting tokens at runtime" example shows --repos repo-a,repo-b for a multi-repo same-org mint. After repos scope hardening, same-org mints must list exactly the requesting repository by default. A multi-repo list is denied unless PER_ORG_FOREIGN_COMPAT is enabled and the caller is .fullsend. This example now suggests a pattern that will fail for most callers.
    Remediation: Update the multi-repo example to clarify it requires PER_ORG_FOREIGN_COMPAT=true and a .fullsend caller, or replace it with a single-repo example (e.g., --repos ${{ github.event.repository.name }}) as the default same-org pattern.

Low

  • [breaking-api-behavior] internal/mintcore/handler.go:244 — POST /v1/token introduces two intentional breaking changes documented in ADR 0077: (1) same-org requests with empty repos or broad repo lists now return 403, (2) cross-org requests with non-empty repos now return 403. Properly documented with PER_ORG_FOREIGN_COMPAT migration path and ! suffix in the PR title.
  • [test-integrity] internal/mintcore/handler_test.go:2433TestHandler_PerRepoUnregistered sends repos:["test-repo"] but the OIDC repository claim is test-org/unregistered-repo. If OIDC verification ever passed, the repos scope check would reject with 403 instead of the expected 401. Currently masked by execution order (OIDC check fires first). Pre-existing pattern, not introduced by this PR.
  • [response-schema-change] internal/mintcore/handler.go:49GET /v1/status adds a new always-present field per_org_foreign_compat (bool, no omitempty). Additive and backward-compatible for standard JSON consumers.
  • [initialization-asymmetry] internal/mintcore/handler.go:96NewHandler reads PER_ORG_FOREIGN_COMPAT from os.Getenv in its struct literal, but NewHandlerFromConfig does not accept a compat parameter. ParseWorkerConfig patches h.perOrgForeignCompat after calling NewHandlerFromConfig. Three constructor paths initialize the same field differently. Currently safe (the post-construction patch is the only caller).
  • [scope-creep] internal/cli/deploy_identity.go — Deploy-commit resolution (resolving git HEAD from local checkout when CLI commit is dev) is not requested by either linked issue (mint: forbid intra-org cross-repo token minting by default; gate org-mode shapes behind a feature flag #5828, mint: support "*" as the explicit org-wide repos signal for cross-org tokens #5829). Well-tested (235 lines of tests) and documented in the PR body, but represents scope beyond the stated intent. Also surfaces Version: and Commit: in deploy summaries.
  • [stale-documentation] docs/guides/infrastructure/mint-administration.md:349 — The "What status reports" section does not mention the new Per-org foreign compat line added to mint status output by this PR.
  • [input-normalization] internal/mintcore/repos_scope.go:19repos:["*"] is normalized to empty repos before validation. On the same-org path, ["*"] → empty → 403. Documented in ADR 0077.
Previous run

Review

Findings

Medium

  • [stale-documentation] docs/guides/infrastructure/mint-administration.md:378 — The "Minting tokens at runtime" example shows --repos repo-a,repo-b for a multi-repo same-org mint. After repos scope hardening, same-org mints must list exactly the requesting repository by default. A multi-repo list is denied unless PER_ORG_FOREIGN_COMPAT is enabled and the caller is .fullsend. This example now suggests a pattern that will fail for most callers.
    Remediation: Update the multi-repo example to clarify it requires PER_ORG_FOREIGN_COMPAT=true and a .fullsend caller, or replace it with a single-repo example (e.g., --repos ${{ github.event.repository.name }}) as the default same-org pattern.

Low

  • [initialization-asymmetry] internal/mintcore/handler.go:99NewHandler reads PER_ORG_FOREIGN_COMPAT from os.Getenv in its struct literal, but NewHandlerFromConfig does not accept a compat parameter. ParseWorkerConfig patches h.perOrgForeignCompat after calling NewHandlerFromConfig. Three constructor paths initialize the same field differently. Currently safe (the post-construction patch is the only caller), but diverges from how other Handler fields are consistently initialized inside constructors.
  • [audit-visibility] internal/mintcore/handler.go:245 — When validateReposScope permits a request under PER_ORG_FOREIGN_COMPAT, the handler does not log which specific compat shape was matched (.fullsend broad-list, enrolled [.fullsend], or {self, .fullsend} pair). Forensic analysis can reconstruct the shape from existing log fields (requested_repos, source_repo), but explicit shape labeling would make incident response faster.
Previous run (2)

Review

Findings

Medium

  • [stale-documentation] docs/guides/infrastructure/mint-administration.md:377 — The "Minting tokens at runtime" example shows --repos repo-a,repo-b for a multi-repo same-org mint. After repos scope hardening, same-org mints must list exactly the requesting repository by default. A multi-repo list is denied unless PER_ORG_FOREIGN_COMPAT is enabled and the caller is .fullsend. This example now suggests a pattern that will fail for most callers.
    Remediation: Update the example to show single-repo usage (e.g., --repos ${{ github.event.repository.name }}) as the default same-org pattern, and add a note that multi-repo lists require PER_ORG_FOREIGN_COMPAT and .fullsend caller identity.

Low

  • [backward-incompatible API behavior change] internal/mintcore/handler.go:240 — POST /v1/token introduces two intentional breaking changes documented in ADR 0077: (1) same-org requests with empty repos now return 403, (2) cross-org requests with non-empty repos now return 403. Properly documented with PER_ORG_FOREIGN_COMPAT migration path and ! suffix in the PR title.
  • [initialization-asymmetry] internal/mintcore/handler.go:182NewHandler reads PER_ORG_FOREIGN_COMPAT from os.Getenv in its struct literal, but NewHandlerFromConfig does not accept a compat parameter. ParseWorkerConfig patches h.perOrgForeignCompat after calling NewHandlerFromConfig. Three constructor paths initialize the same field differently. Currently safe (the post-construction patch is the only caller), but diverges from how other Handler fields are consistently initialized inside constructors.
  • [audit-visibility] internal/mintcore/handler.go:240 — When validateReposScope permits a request under PER_ORG_FOREIGN_COMPAT, the handler does not log which specific compat shape was matched (.fullsend broad-list, enrolled [.fullsend], or {self, .fullsend} pair). Forensic analysis can reconstruct the shape from existing log fields (requested_repos, source_repo), but explicit shape labeling would make incident response faster.
  • [scope-creep] internal/cli/deploy_identity.go — Deploy-commit resolution (resolving git HEAD from local checkout when CLI commit is dev) is not requested by either linked issue (mint: forbid intra-org cross-repo token minting by default; gate org-mode shapes behind a feature flag #5828, mint: support "*" as the explicit org-wide repos signal for cross-org tokens #5829). Well-tested (235 lines of tests) but represents scope beyond the stated intent. The PR description documents it.
  • [missing-documentation] docs/guides/infrastructure/mint-administration.md:349 — The "What status reports" section does not mention the new Per-org foreign compat line added to mint status output by this PR.
  • [api-response-schema-change] internal/mintcore/handler.go:135GET /v1/status adds a new always-present field per_org_foreign_compat (bool, no omitempty). Additive and backward-compatible for standard JSON consumers; documented in the infrastructure reference and standalone mint guides.
Previous run (3)

Review

Findings

Medium

  • [fail-open / default-deny gap] internal/mintcore/repos_scope.go:48 — When PER_ORG_FOREIGN_COMPAT is enabled, a .fullsend caller passes validateReposScope for any non-empty repos list without further content validation (line 58: immediate return nil). This is documented behavior per ADR 0077, but audit visibility is limited — the handler does not log which specific compat shape was matched when a broader-than-self scope is allowed. Post-incident forensics would benefit from knowing whether a given mint request used the .fullsend broad-list shape, the enrolled [.fullsend] shape, or the {self, .fullsend} pair.
    Remediation: Add a log line in handler.go when compat allows a broader-than-self scope (e.g., repos scope allowed via PER_ORG_FOREIGN_COMPAT: caller=%s repos=%v shape=<matched-shape>).
  • [stale-documentation] docs/guides/infrastructure/mint-administration.md:377 — The "Minting tokens at runtime" example shows --repos repo-a,repo-b for a multi-repo same-org mint. After repos scope hardening, same-org mints must list exactly the requesting repository by default. A multi-repo list is denied unless PER_ORG_FOREIGN_COMPAT is enabled and the caller is .fullsend. This example now suggests a pattern that will fail for most callers.
    Remediation: Replace the multi-repo example with a single-repo example matching the requesting repo (e.g., --repos ${{ github.event.repository.name }}). If showing multi-repo is still desired, add a note that it requires PER_ORG_FOREIGN_COMPAT and is limited to .fullsend callers.

Low

  • [backward-incompatible API behavior change] internal/mintcore/handler.go:240 — POST /v1/token introduces two intentional breaking changes: (1) same-org requests with empty repos now return 403, (2) cross-org requests with non-empty repos now return 403. Properly documented in ADR 0077 with PER_ORG_FOREIGN_COMPAT migration path and ! suffix in the PR title. Error messages describe the denial reason but could include actionable guidance (e.g., suggesting repos: ["<requesting-repo>"] for same-org callers).
  • [initialization-asymmetry] internal/mintcore/handler.go:91NewHandler reads PER_ORG_FOREIGN_COMPAT from os.Getenv in its struct literal, but NewHandlerFromConfig does not accept a compat parameter. ParseWorkerConfig patches h.perOrgForeignCompat after calling NewHandlerFromConfig. Three constructor paths initialize the same field differently. Currently safe (the post-construction patch is the only caller), but diverges from how other Handler fields are consistently initialized inside constructors.
  • [scope-creep] internal/cli/deploy_identity.go — Deploy-commit resolution (resolving git HEAD from local checkout when CLI commit is dev) is not requested by either linked issue (mint: forbid intra-org cross-repo token minting by default; gate org-mode shapes behind a feature flag #5828, mint: support "*" as the explicit org-wide repos signal for cross-org tokens #5829). Well-tested (235 lines of tests) but represents scope beyond the stated intent. The PR description documents it.
  • [missing-documentation] docs/guides/infrastructure/mint-administration.md:349 — The "What status reports" section does not mention the new Per-org foreign compat line added to mint status output by this PR.
  • [missing-cross-reference] docs/guides/dev/e2e-testing.md:53 — States "repos omitted for installation-wide access" for cross-org mints without clarifying same-org cannot do this. The cross-org description is technically correct, but a reader might infer the pattern generalizes.
Previous run (4)

Review

Findings

Medium

  • [stale-documentation] docs/guides/infrastructure/mint-administration.md:377 — The "Minting tokens at runtime" example shows --repos repo-a,repo-b for a multi-repo same-org mint. After repos scope hardening, same-org mints must list exactly the requesting repository by default. A multi-repo list is denied unless PER_ORG_FOREIGN_COMPAT is enabled and the caller is .fullsend. This example now suggests a pattern that will fail for most callers.
    Remediation: Replace the multi-repo example with a single-repo example matching the requesting repo (e.g., --repos ${{ github.event.repository.name }}). If showing multi-repo is still desired, add a note that it requires PER_ORG_FOREIGN_COMPAT and is limited to .fullsend callers.
  • [truthy-parsing-duplication] internal/cli/mint.go:96perOrgForeignCompatLabel duplicates the truthy-value parsing logic (1/true/yes with ToLower+TrimSpace) that envTruthy in internal/mintcore/repos_scope.go already provides. The CLI package imports mintcore elsewhere in this file. Duplicating truthy parsing risks the two diverging on accepted values.
    Remediation: Export mintcore.EnvTruthy and call it from perOrgForeignCompatLabel, or extract the truthy check so both sites share one definition.

Low

  • [stale-comment] internal/mintcore/handler_test.go:1411 — Comment // test-org/.fullsend on the signToken(t, nil) call is stale. The default repository claim was changed from test-org/.fullsend to test-org/test-repo earlier in this PR. The test logic remains correct but the misleading comment could confuse future readers.
  • [test-style] internal/cli/mint_test.go:171TestRunMintDeployGCP_SkipDeployReportsCommitResolution captures stdout via os.Pipe, which is unusual compared to neighboring tests. This is justified because runMintDeployGCP hardcodes printer := ui.New(os.Stdout) and does not accept an injected writer.
  • [missing-documentation] docs/guides/infrastructure/mint-administration.md:349 — The "What status reports" section does not mention the new Per-org foreign compat line added to mint status output by this PR.
  • [missing-cross-reference] docs/guides/dev/e2e-testing.md:53 — States "repos omitted for installation-wide access" for cross-org mints without clarifying same-org cannot do this. The cross-org description is technically correct, but a reader might infer the pattern generalizes.
Previous run (5)

Review

Findings

Medium

  • [breaking-change-api-contract] internal/mintcore/handler.go:330 — POST /v1/token now denies same-org requests with empty repos (installation-wide tokens) with 403. This is an intentional, documented breaking change per ADR 0077. PER_ORG_FOREIGN_COMPAT provides a migration path but does not restore installation-wide same-org tokens.
  • [breaking-change-api-contract] internal/mintcore/handler.go:294repos: ["*"] normalization converts to empty before validation. On the same-org path this means ["*"] → empty → 403. Intentional per ADR 0077 section 1.
  • [breaking-change-api-contract] internal/mintcore/repos_scope.go:46 — Foreign (cross-org) mints now deny non-empty repos lists with 403. Intentional restriction documented in ADR 0077 section 2.
  • [authorization / fail-open] internal/mintcore/repos_scope.go:61 — When PER_ORG_FOREIGN_COMPAT is enabled and the caller is .fullsend, validateReposScope permits any non-empty repos list (up to maxRepos=500). Accepted design per ADR 0077, but makes .fullsend a high-value target when compat is on.
  • [missing-authorization] docs/ADRs/0077-mint-repos-scope-hardening.md — PR has no linked issue. For a significant architectural change (1200+ lines, breaking change, new ADR), an authorizing issue provides traceability. The PR body and ADR are detailed.
  • [stale-documentation] docs/ADRs/0060-cross-org-mint-authorization-via-org-variables.md:79 — ADR 0060 Consequences section still states installation-wide tokens are permitted on both paths, contradicting the new same-org denial. A "Later note" was added referencing ADR 0077, but the original claim remains. (ADRs are immutable records; the later note is the standard update mechanism.)
  • [incomplete-documentation] docs/architecture.md — The cross-org bullet was updated and a new "Mint repos scope" bullet added (line 86), but the cross-org bullet could more explicitly note that foreign mints now require empty repos.

Low

  • [scope-alignment] internal/cli/deploy_identity.go — Deploy identity stamping is a separate feature from repos scope hardening, bundled in this PR. Well-tested but represents scope beyond the stated intent.
  • [architectural-coherence] internal/mintcore/repos_scope.go — Org-mode exception logic hardcodes .fullsend as a special repository. ADR 0077 documents this but doesn't cross-reference the architectural basis for .fullsend's elevated mint authority.
  • [information disclosure] internal/mintcore/handler.go:341/v1/status now exposes per_org_foreign_compat to authenticated callers. Acceptable since the endpoint requires OIDC auth.
  • [comment-style] internal/mintcore/repos_scope.go:10normalizeMintRepos comment says "installation-wide scope on the foreign path" but normalization runs before path selection, affecting both paths.
  • [comment-style] internal/cli/deploy_identity.go:14revParse variable comment uses passive voice; codebase prefers active voice.
  • [comment-style] internal/cli/deploy_identity.go:51resolveAndReportMintDeployCommit comment mixes side effects in summary.
  • [test-naming] internal/cli/deploy_identity_test.go:224TestResolveMintDeployCommit_PreservesNonDev could be more descriptive.
  • [function-organization] internal/cli/mint.go:437perOrgForeignCompatLabel is defined far from its only call site in runMintStatus.
  • [typescript-comment] internal/dispatch/cf/workersrc/src/index.ts:493PER_ORG_FOREIGN_COMPAT comment could be more specific about "org-mode repos scope exceptions."
  • [doc-style] docs/guides/infrastructure/standalone-mint.md:113PER_ORG_FOREIGN_COMPAT table entry is verbose for the table format.
  • [embed-file-duplication] internal/dispatch/gcf/mintsrc/mintcore/repos_scope.go.embed — Exact duplicate of repos_scope.go following the existing embed pattern, but no automated sync check exists.
  • [missing-documentation] docs/guides/infrastructure/infrastructure-reference.md:97 — Status endpoint docs add per_org_foreign_compat with brief explanation; could note the flag's effect on repos scope.
  • [missing-documentation] docs/guides/infrastructure/standalone-mint.md:113 — Config table entry includes examples but could link to ADR 0077.
  • [outdated-example] docs/guides/infrastructure/standalone-mint.md:308 — Example workflow doesn't note that omitting repos is now forbidden for same-org requests.
  • [missing-cross-reference] docs/guides/dev/e2e-testing.md:53 — States "repos omitted for installation-wide access" for cross-org mints without clarifying same-org cannot do this.
  • [additive-change-schema] internal/mintcore/handler.go:135GET /v1/status adds per_org_foreign_compat (bool, always present). Backward-compatible for clients ignoring unknown fields.
  • [breaking-change-api-contract] internal/dispatch/cf/workersrc/src/index.ts:708WorkerConfig adds PerOrgForeignCompat field. Internal struct; ParseWorkerConfig handles missing/empty gracefully.
  • [behavioral-change] internal/mintcore/handler.go:336 — WARNING log for empty repos now fires only after validateReposScope passes, so same-org callers never see it (they get 403 instead).
Previous run (6)

Review

Reason: stale-head

The review agent reviewed commit 366cfd38bc052a9961e29fefc8e1d924fdfb9433 but the PR HEAD is now bdd3db78305fbaeff12943778f576bc35f542a46. This review was discarded to avoid approving unreviewed code.

Previous run (7)

Review

Findings

Medium

  • [test integrity] internal/mintcore/testmain_test.go:15TestMain now defaults PER_ORG_FOREIGN_COMPAT to "true", which means all existing handler tests using the default .fullsend repository claim with arbitrary repos lists pass silently under the relaxed compat mode. Tests like TestHandler_FullFlow never exercise the default-deny repos scope path because the .fullsend caller with compat=on bypasses the scope check entirely. This reduces coverage of the new security hardening for the most common handler test pattern.
    Remediation: Consider not setting PER_ORG_FOREIGN_COMPAT in TestMain and instead having each test that needs compat explicitly opt in with t.Setenv("PER_ORG_FOREIGN_COMPAT", "true") or h.perOrgForeignCompat = true.

Low

  • [error handling] internal/mintcore/repos_scope.go — The error message "repos scope not allowed for requesting repository" is reused for three distinct denial reasons: (1) same-org empty repos, (2) same-org repos list mismatch with compat off, (3) compat-mode shapes that don't match allowed patterns. The foreign-path denial has its own distinct message, but same-org denials are indistinguishable, making operational debugging harder.
  • [breaking-request-validation] internal/mintcore/handler.go — POST /v1/token now enforces strict same-org repos scope validation. Same-org requests with empty repos are denied (403). Callers must set repos=["requesting-repo-name"] or operators must enable PER_ORG_FOREIGN_COMPAT. Properly documented as intentional breaking change per ADR 0077 and the ! suffix in the PR title.
  • [breaking-request-validation] internal/mintcore/repos_scope.go — Foreign (cross-org) mint requests must use empty repos; non-empty repos arrays are denied (403). Callers can use repos=["*"] (normalized to empty) or omit the field. Documented in ADR 0077.
  • [normalization-behavior] internal/mintcore/repos_scope.gorepos=["*"] is normalized to empty repos before validation, so same-org callers using ["*"] receive 403 (same as empty repos). Consistent with the breaking change but may surprise callers who expected ["*"] to differ from empty on the same-org path.
  • [scope-alignment] internal/cli/deploy_identity.go — Deploy identity stamping (git rev-parse commit resolution for mint deploys) is a secondary feature bundled with the primary repos scope hardening. It is mentioned in the PR body but not in ADR 0077 or the PR title.

Labels: PR modifies mint core authorization logic (internal/mintcore/) and adds security hardening for repos scope

fullsend-ai-review[bot]

This comment was marked as outdated.

@fullsend-ai-review fullsend-ai-review Bot added requires-manual-review Review requires human judgment component/mint Token mint and cross-boundary credentials security Security threat model and related concerns labels Aug 2, 2026
@ifireball ifireball self-assigned this Aug 2, 2026
Update embedded zip file count, wire PER_ORG_FOREIGN_COMPAT into the CF
Worker config JSON, stop enabling compat in TestMain by default, return
distinct repos-scope errors, and warn when checkout commit resolution fails.

Signed-off-by: Barak Korren <bkorren@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@fullsend-ai-review

fullsend-ai-review Bot commented Aug 2, 2026

Copy link
Copy Markdown

🤖 Review · ⚠️ Cancelled · Started 9:35 AM UTC · Ended 9:43 AM UTC
Commit: 833d11f · View workflow run →

Include gofmt fix for handler_test.go map alignment that failed CI lint.

Signed-off-by: Barak Korren <bkorren@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@fullsend-ai-review

fullsend-ai-review Bot commented Aug 2, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 9:44 AM UTC · Completed 10:00 AM UTC
Commit: 366cfd3 · View workflow run →

@codecov

codecov Bot commented Aug 2, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

fullsend-ai-review[bot]

This comment was marked as outdated.

Keep early source-dir resolution for dry-run from fullsend-ai#5763 and deploy-commit
stamping from this branch; retain both sets of deploy tests.

Signed-off-by: Barak Korren <bkorren@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@fullsend-ai-review

fullsend-ai-review Bot commented Aug 3, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 7:06 AM UTC · Completed 7:21 AM UTC
Commit: da38882 · View workflow run →

Comment thread internal/mintcore/config.go
Comment thread internal/mintcore/handler.go Outdated
Comment thread internal/mintcore/repos_scope.go
Comment thread internal/dispatch/gcf/mintsrc/mintcore/repos_scope.go.embed
Comment thread internal/mintcore/repos_scope.go

@rh-hemartin rh-hemartin left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

In general looks good to me, the only stuff I'm not sure about is the nil returning as []string type, otherwise the rest is purely cosmetic. Since there are no changes to the actions I guess they are properly configured and always pass repos to their requests.

ifireball and others added 2 commits August 3, 2026 12:25
Rename the cross-org boolean to isTargetForeign, use strings.Split for
bare repo names, and add a blank line before the two-repo compat check.

Signed-off-by: Barak Korren <bkorren@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
merge: sync harden-mint-repos-scope with upstream/main
@fullsend-ai-review

fullsend-ai-review Bot commented Aug 3, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 9:29 AM UTC · Completed 9:44 AM UTC
Commit: a29042c · View workflow run →

fullsend-ai-review[bot]

This comment was marked as outdated.

ifireball and others added 2 commits August 3, 2026 13:15
Return a shape label from validateReposScope and log it when a compat
exception allows broader-than-self same-org repos for auditability.

Signed-off-by: Barak Korren <bkorren@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
merge: sync harden-mint-repos-scope with upstream/main
@fullsend-ai-review

fullsend-ai-review Bot commented Aug 3, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 10:16 AM UTC · Completed 10:35 AM UTC
Commit: fb8dd18 · View workflow run →

@fullsend-ai-review fullsend-ai-review 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.

See the review comment for full details.


Note: The following inline comments could not be posted on the diff (GitHub returned 422) and are included here instead:

  • internal/mintcore/handler.go:244: [low] breaking-api-behavior

POST /v1/token introduces two intentional breaking changes documented in ADR 0077: (1) same-org requests with empty repos or broad repo lists now return 403, (2) cross-org requests with non-empty repos now return 403. Properly documented with PER_ORG_FOREIGN_COMPAT migration path and ! suffix in PR title.

  • internal/mintcore/handler_test.go (file-level): Line 2433 · [low] test-integrity

TestHandler_PerRepoUnregistered sends repos test-repo but OIDC claim is test-org/unregistered-repo. If OIDC ever passed, repos scope check would reject with 403 instead of expected 401. Pre-existing pattern, not introduced by this PR.

  • internal/mintcore/handler.go:49: [low] response-schema-change

GET /v1/status adds new always-present field per_org_foreign_compat (bool, no omitempty). Additive and backward-compatible.

  • internal/mintcore/handler.go:96: [low] initialization-asymmetry

NewHandler reads PER_ORG_FOREIGN_COMPAT from os.Getenv but NewHandlerFromConfig does not accept a compat parameter. ParseWorkerConfig patches afterward. Three constructor paths initialize differently. Currently safe.

  • internal/mintcore/repos_scope.go:19: [low] input-normalization

repos * is normalized to empty repos before validation. On same-org path this means 403. Documented in ADR 0077.

@ifireball
ifireball added this pull request to the merge queue Aug 3, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Aug 3, 2026
@ifireball
ifireball added this pull request to the merge queue Aug 3, 2026
Merged via the queue into fullsend-ai:main with commit 7832fe1 Aug 3, 2026
19 checks passed
@ifireball
ifireball deleted the harden-mint-repos-scope branch August 3, 2026 11:28
@fullsend-ai-retro

fullsend-ai-retro Bot commented Aug 3, 2026

Copy link
Copy Markdown

🤖 Finished Retro · ✅ Success · Started 11:30 AM UTC · Completed 11:44 AM UTC
Commit: fb8dd18 · View workflow run →

@fullsend-ai-retro

Copy link
Copy Markdown

Retro: PR #5826 — feat(mint)!: harden repos scope against cross-repo minting

Workflow overview

This was a human-authored (via Cursor) security-critical PR by @ifireball: 22 files changed, +1180/−93 lines, 14 commits over ~26 hours. The PR hardened mint repos authorization to prevent cross-repo minting attacks, introduced a PER_ORG_FOREIGN_COMPAT feature flag, added deploy commit stamping, and documented the policy in ADR 0077. It fixed issues #5828 and #5829.

Agent activity: 9 review agent runs (7 successful, 2 cancelled via stale-head detection), 0 code/fix/triage runs (human-authored PR). Agents repo: fullsend-ai/agents at commit a0fec95.

Review quality assessment

This PR demonstrated strong complementarity between human and bot review — neither alone would have caught all issues:

Reviewer Unique findings Key catches
rh-hemartin (human) 3 unique Variable naming (hasForeignisTargetForeign), idiomatic Go (strings.Split), formatting
fullsend-ai-review 4 unique actionable TestMain test integrity, truthy-parsing DRY, fail-open audit gap, stale comment
qodo-code-review 2 unique CF Worker compat flag not serialized (critical bug), silent git fallback

The most impactful finding — a real correctness bug where Cloudflare Worker deployments would silently fail to honor PER_ORG_FOREIGN_COMPAT — was caught by qodo but missed by fullsend-ai-review across all 7 successful runs. The human reviewer also missed it. This is a cross-language gap: the Go config struct gained a new field but the TypeScript CF Worker adapter never serialized it.

6 bot findings were fixed by the author. The human reviewer's 3 naming/idiom catches were also all fixed. One human finding (nil vs empty slice) was a false positive that the author corrected with a Go semantics explanation.

Evidence for existing issues

  • fullsend#4069 (Reduce review dispatch frequency during rapid fix-commit iterations): Runs 5–7 on Aug 3 were triggered by merge commits and a single variable rename. All 3 produced zero new findings, consuming ~52 minutes of compute for pure repetition of earlier observations.

  • fullsend#2959 (Deduplicate findings across re-review iterations): The "stale-documentation" finding about mint-administration.md appeared in 5 of 7 successful runs. The "initialization-asymmetry" and "scope-creep" findings each appeared in 4+ runs.

  • fullsend#1525 (Cross-file impact analysis): The review agent missed the config struct field not propagated to the TypeScript CF Worker adapter — the single most critical finding on the PR. This is a concrete instance of the cross-file impact analysis gap, with a specific pattern (config struct → adapter serialization).

  • fullsend#4107 (Overlapping findings between fullsend and qodo): The two bots have complementary strengths — fullsend-ai-review excels at test integrity, code duplication, and security audit concerns; qodo excels at cross-file correctness bugs and process compliance. No finding overlapped between them.

What went well

  • The review agent correctly identified the TestMain default masking security hardening — a subtle test integrity issue the author fixed immediately.
  • The truthy-parsing duplication finding led to a clean EnvTruthy export that eliminated a real DRY violation.
  • Stale-head detection correctly cancelled 2 obsolete runs, preventing wasted review comments.
  • The sticky comment pattern provided good UX, consolidating findings across runs without comment spam.
  • The author was highly responsive, fixing 9 out of 11 actionable findings from all reviewers within hours.
  • The requires-manual-review label was correctly applied for this security-critical breaking change.

Proposals filed

ifireball pushed a commit to ifireball/fullsend that referenced this pull request Aug 4, 2026
resolveE2EToken in pkg/e2etest/auth.go previously omitted
the Repos field, relying on the legacy empty-repos signal
for org-wide tokens. Now that mint accepts "*" as the
explicit org-wide form (PR fullsend-ai#5826), pass Repos: ["*"] so the
e2e suite is ready for repos becoming mandatory (fullsend-ai#5831).

Closes fullsend-ai#5830
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

component/mint Token mint and cross-boundary credentials requires-manual-review Review requires human judgment security Security threat model and related concerns

Projects

None yet

2 participants