Skip to content

feat: add safe managed bundle refresh - #225

Open
danielewood wants to merge 24 commits into
mainfrom
feat/safe-bundle-refresh
Open

danielewood wants to merge 24 commits into
mainfrom
feat/safe-bundle-refresh

Conversation

@danielewood

@danielewood danielewood commented Sep 20, 2026 •

Copy link
Copy Markdown
Collaborator

Description

Scanning an accumulated vendor-delivery directory could overwrite unrelated or newer managed bundles, reuse input passwords for output encryption, and silently skip expected output. Managed refreshes now show a complete plan before writing, with explicit scope, replacement checks, and separate output credentials.

  • scan --bundle-path previews by default; --write applies the plan. Repeat --bundle-name / --only to limit output, and use --require-bundle / --fail-on-skip for automation. Empty selections and invalid configuration fail explicitly.
  • Compare the selected leaf with existing output and block expiration downgrades, equal-expiry conflicts, and ambiguous replacements unless --force is provided. Pin each plan to an absolute resolved output destination and check directory identity. Preflight every bundle, recheck scope, existing contents, candidate validity, and the planned trusted chain after staging and immediately before replacement, serialize refreshes with a lock, and retain staged directory replacement/rollback.
  • Keep scan input passwords separate from output encryption. --output-password-file encrypts PEM keys and sets the P12 password. Without it, P12 preserves the intentional changeit default and PEM keys remain unencrypted. Default artifacts include PEM certificates/key, a P12 archive, and JSON metadata. --formats selects additional or fewer artifacts.
  • Select certificates by expiry, issuance time, and SHA-256 fingerprint. Report the selected source, key source, config rule, identity, validity, trust, files, unselected candidates with tie-break reasons, and created/replaced/skipped decisions in text/JSON and each saved manifest.json.
  • Reserve all selected primary directories before candidate lookup, including missing candidates; reject colliding CN-derived names within a rule while allowing explicit grouping. Reject sanitized, case, and Unicode aliases, protect unselected rules and existing manifest identities, and reject reserved names and control characters in directories and artifacts.
  • Keep declared config, password, and database files outside managed output. Exclude output/password/database paths and their symlink, case, and Unicode aliases from raw ingestion, preserve explicit database imports, and honor explicitly chosen scan roots named vendor. Document the complete workflow in top-level help, README, examples, and architecture notes.

Breaking changes: Existing managed-export scripts must add --write, choose extra artifacts explicitly, and use --output-password-file for output encryption. bundle and convert retain their existing password behavior. --force still permits untrusted certificates and now also overrides replacement conflicts. Expired leaves separately require --allow-expired; with verification enabled, their chains are checked at the leaf issuance time, disclosed in chain warnings. Future-dated leaves remain ineligible even with force or the expired-certificate override.

Test Plan

  • gopls check passed for all changed Go files.
  • Full pre-commit run --all-files passed, including Go race tests, lint/vulnerability checks, generated docs, WASM/Cloudflare builds, and 129 web tests.
  • Behavioral regressions for scope, deterministic ties, downgrade/conflict protection, explicit overrides, missing/required bundles, stale plans and validity, directory/artifact aliases, control-file protection, symlinks, concurrent writers, public-only exports, artifact selection, and provenance.
  • CLI tests with encrypted P12 and ZIP deliveries, distinct input/output passwords (including spaces), default P12 password round-trips, expiry policy, preview/write behavior, JSON manifests, and invalid options.
  • Built CLI smoke test: preview creates no output; explicit write creates selected files; a downgrade exits 2 and leaves existing output unchanged.
  • Real certificate-management setup: previews reported 15 planned and 24 skipped bundles; an isolated copy replaced the same 15 and preserved skipped directories. Required stale exports failed, expiration downgrades stayed blocked with --allow-expired, the original tree was unchanged, and temporary private artifacts were removed.

Checklist

  • Conventional Commit messages and signed commits.
  • Changelog includes compatibility changes.
  • CLI docs regenerated and examples updated.

Limits

Each bundle uses staged directory replacement with rollback; the refresh is not a transaction across all directories. A later write-time error may leave earlier bundles applied; their statuses remain visible in the manifest. A replacement committed before backup cleanup fails retains its replaced status; the error identifies the retained backup path and later writes stop. A killed process can leave the refresh lock requiring removal after confirming no writer remains.

Preview scoped bundle changes before writing, protect existing leaves from unsafe replacement, and separate input decryption from output encryption. Report deterministic selection and provenance, support artifact selection and required bundles, and cover the workflow with behavioral regressions.
@danielewood
danielewood marked this pull request as ready for review September 20, 2026 11:57
Copilot AI lite review requested due to automatic review settings September 20, 2026 11:57
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 20, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-22T13:49:47.304807Z 138394e New commits
ℹ️ About Codex in GitHub

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

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

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

Copilot AI 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.

Copilot review overview

🟡 Changes recommended

Unresolved critical symlink-exclusion and moderate expiry, planning, and provenance issues block approval.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 1 High severity · 2 Medium severity · 1 Low severity

Open (4)
What changed in this PR

Adds a preview-first managed bundle refresh workflow with scoped selection, replacement safety, separate credentials, selectable artifacts, manifests, and documentation.

Changes:

  • Adds planning, validation, locking, stale-plan checks, staging, rollback, and preview/write behavior.
  • Adds separate input/output password handling and format-aware artifact generation.
  • Updates CLI integration, tests, documentation, changelog, architecture notes, and dependencies.
File Reviewed changes and findings
web/​package-lock.json Updates locked web dependencies.
README.md Documents the managed refresh workflow and artifacts.
internal/​scanwalk.go Adds scan exclusions and vendor-root handling. Findings: Critical (3 votes): use canonical/evaluated paths to prevent symlink bypasses. Nit (1 vote): wrap exclusion errors with context while preserving the cause.
internal/​scanwalk_test.go Tests scan exclusions.
internal/​certstore/​memstore.go Adds deterministic certificate ordering.
internal/​certstore/​export.go Adds artifact selection and key validation. Findings: Nit (2 votes): wrap key/certificate mismatch errors with context while preserving errors.Is. Nit (1 vote): add table-driven coverage for all supported formats and key/password rules.
internal/​certstore/​export_formats.go Defines supported and default formats.
internal/​bundleplan.go Implements planning, validation, and writes. Findings: Moderate (2 votes): pass expiry policy independently from trust verification. Moderate (2 votes): represent skipped duplicate candidates in the plan. Moderate (1 vote): record Forced whenever force overrides verification.
internal/​bundleplan_test.go Tests planning and replacement behavior.
internal/​bundleplan_existing.go Inspects existing bundle contents and detects stale changes.
EXAMPLES.md Updates managed refresh examples. Finding: Nit (1 vote): clarify that missing keys fail only for key-dependent formats.
cmd/​certkit/​scan.go Integrates managed planning into scanning.
cmd/​certkit/​scan_export.go Adds refresh flags, credentials, and rendering.
cmd/​certkit/​scan_export_test.go Tests CLI refresh workflows.
cmd/​certkit/​root.go Updates top-level help.
cmd/​certkit/​readonly_commands_test.go Updates scan test state handling.
CHANGELOG.md Records the feature and breaking changes.
.claude/​docs/​architecture.md Documents new planning components.
Files not reviewed (1)
  • web/package-lock.json: Generated file

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread internal/scanwalk.go Outdated
Comment thread internal/bundleplan.go
Comment thread internal/bundleplan.go
Comment thread internal/certstore/export.go Outdated
Keep the intentional changeit P12 fallback without reusing input credentials. Canonicalize scan exclusions, explain unselected candidates, and enforce expiry opt-in independently of trust overrides.
Copilot AI review requested due to automatic review settings September 20, 2026 13:54

Copilot AI 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.

Copilot review overview

🔵 Needs a closer look

Two moderate findings in bundle.go and internal/bundleplan.go remain unresolved; the remaining feedback is minor.

Review effort: Lite
Findings: None

Resolved since last review (4)
Files not reviewed (1)
  • web/package-lock.json: Generated file

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: bbe49920c7

ℹ️ About Codex in GitHub

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

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

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

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

Comment thread internal/bundleplan_existing.go Outdated
Comment thread internal/bundleplan.go Outdated
Comment thread internal/bundleplan.go Outdated
Recognize selected CA certificates in manifests, retain valid configured names for duplicate Kubernetes Secrets, and scope required-bundle checks to the primary directory so optional historical skips do not block it.
Copilot AI review requested due to automatic review settings September 20, 2026 18:54

Copilot AI 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.

Copilot review overview

🔵 Needs a closer look

Moderate findings remain around default-password warning visibility and artifact-selection test coverage.

Review effort: Lite
Findings: None

Files not reviewed (1)
  • web/package-lock.json: Generated file
Previously missed (1)

In code that hasn't changed since last review

Medium severity Always emit changeit security warning

internal/​bundleplan.go:146

The managed path emits the changeit fallback warning through slog.Warn, so --log-level error suppresses it even though the command still creates a P12 protected by the well-known default. This differs from bundle/convert, which write the warning directly to stderr; emit this security warning independently of the configured log level (or return a plan flag for the CLI to report).

CSR metadata is not an existing leaf certificate. Ignore it during replacement checks while keeping malformed certificate protection and identifying the offending artifact. Keep the intentional changeit fallback warning visible even at error log level.
Copilot AI review requested due to automatic review settings September 20, 2026 19:14
@danielewood

Copy link
Copy Markdown
Collaborator Author

Fixed in 3cb05ec. Addressed the default-password warning feedback: managed scans now write the warning directly to stderr, independently of the configured log level. The intentional changeit fallback is unchanged. CLI regression coverage runs with error-level logging and checks both warning visibility and suppression when an explicit output password is supplied or P12 is omitted.

Functional testing against an existing certificate-management setup also found that legacy .csr.json files were being treated as certificate metadata. Refresh now ignores CSR metadata when identifying the installed leaf; malformed certificate artifacts still block replacement and identify the offending filename. Synthetic regressions cover complete legacy and managed bundles.

Validation: scoped previews and isolated replacement writes with real inputs; deterministic selection and archive provenance; exact selected artifact lists; unselected-directory preservation; leaf/key matching and chain verification with OpenSSL; default and explicit P12 passwords; explicit PEM encryption; private-file permissions; and downgrade protection. The source setup was unchanged, and temporary private-key copies were removed. All repository pre-commit checks and Go language-server diagnostics pass.

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3cb05ec7bc

ℹ️ About Codex in GitHub

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

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

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

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

Comment thread internal/bundleplan.go Outdated

Copilot AI 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.

Copilot review overview

🟡 Changes recommended

Four unresolved review findings remain, including a critical scan-exclusion issue.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 1 High severity · 1 Medium severity

Open (2)
Files not reviewed (1)
  • web/package-lock.json: Generated file
Previously missed (1)

In code that hasn't changed since last review

Low severity Use lowercase kubernetes in validation error

internal/​bundleplan.go:178

ERR-4: this new validation error contains uppercase Kubernetes, but project error strings must be lowercase (CLAUDE.md:89). Use kubernetes in the wrapped error text so this path follows the repository's error contract.

Comment thread cmd/certkit/scan.go Outdated
Comment thread cmd/certkit/scan_export.go Outdated
Skip candidates that cannot be exported before comparing installed leaves. Exclude dump outputs from ingestion and abort before managed writes if the default-password warning cannot be displayed.
Copilot AI review requested due to automatic review settings September 20, 2026 21:25
@danielewood

Copy link
Copy Markdown
Collaborator Author

Fixed in 4d41ab9. Addressed the latest review feedback, including the review-summary request to lowercase kubernetes in the validation error. Optional expired/keyless candidates now skip before replacement checks; existing dump paths are excluded from ingestion; and a failed default-password diagnostic aborts before any managed writes. The intentional changeit fallback remains unchanged.

Regression tests cover optional versus required/scoped skips, preserved downgrade protection, stale key/certificate dumps, and closed stderr. Functional checks against the real certificate-management setup confirmed successful unscoped previews and isolated writes while preserving skipped directories. The original setup was unchanged, and the temporary private-key copies were removed. Full pre-commit checks and Go language-server diagnostics passed.

Copilot AI 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.

Copilot review overview

🔵 Needs a closer look

Three moderate findings and three documentation/error-string nits remain unresolved.

Review effort: Lite
Findings: None

Resolved since last review (2)
Files not reviewed (1)
  • web/package-lock.json: Generated file

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4d41ab9fd6

ℹ️ About Codex in GitHub

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

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

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

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

Comment thread internal/bundleplan.go Outdated
Comment thread internal/bundleplan.go Outdated
Comment thread internal/bundleplan.go Outdated
Optional untrusted deliveries cannot replace anything and must not block unrelated exports. Verify trust before replacement checks, and reject collisions with the managed manifest and refresh lock before writing.
Copilot AI review requested due to automatic review settings September 20, 2026 23:07
@danielewood

Copy link
Copy Markdown
Collaborator Author

Fixed the two concrete review-summary points in d5adf4a. Managed writes now recheck cancellation, directory scope, candidate validity/trust, and existing contents after artifact staging, immediately before replacement. The final manifest is generated after those checks. Regressions simulate edits to the current bundle and to a later bundle while the first bundle is staged; the edits survive, the affected entry is blocked, earlier commits retain their status, and staged artifacts are removed.

Malformed certificate and manifest diagnostics also retain the offending filename when a directory has zero or multiple identifiable leaves, rather than being overwritten by a generic ambiguity message.

The diff-thread fixes for case/Unicode scan exclusions and control characters in artifact names are included in the same commit. Focused reproductions failed before those fixes and pass now. Full pre-commit checks, Go language-server diagnostics, and real-data previews/isolated writes pass. The original certificate-management tree remains unchanged; temporary private artifacts were removed. The intentional changeit fallback is preserved.

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d5adf4ab25

ℹ️ About Codex in GitHub

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

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

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

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

Comment thread internal/bundleplan.go Outdated
Comment thread internal/bundleplan.go Outdated

Copilot AI 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.

Copilot review overview

🟡 Changes recommended

A critical duplicate-derived-name collision can merge distinct bundles; the write-time error labeling nit also remains.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 2 High severity · 1 Low severity

Open (3)
Files not reviewed (1)
  • web/package-lock.json: Generated file

Comment thread internal/bundleplan.go Outdated
Comment thread internal/bundleplan.go Outdated
Keep output targets stable across working-directory and symlink changes, reject derived-name collisions within one rule, and retain bundle names in early write failures.
Copilot AI review requested due to automatic review settings September 21, 2026 01:31

Copilot AI 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.

Copilot review overview

🔵 Needs a closer look

Address the AIA bundle-name omission and malformed JSON/YAML replacement risks; the contextual error wrapper is also outstanding.

Review effort: Lite
Findings: 1 High severity

Open (1)
Resolved since last review (2)
Files not reviewed (1)
  • web/package-lock.json: Generated file

Assign configured bundle names after AIA ingestion so fetched CAs are eligible for export. Block malformed existing JSON/YAML metadata even beside a valid leaf, and preserve managed-export error context.
Copilot AI review requested due to automatic review settings September 21, 2026 13:40
@danielewood

Copy link
Copy Markdown
Collaborator Author

Fixed the three concrete points in the latest review overview in 19d2bad:

  • Bundle names are assigned after AIA resolution, so fetched CA certificates can match configured exports. A local HTTP AIA regression exercises both preview and write, including selected bundle identity and source provenance.
  • Malformed JSON/YAML certificate metadata now blocks replacement even when a neighboring PEM contains a valid leaf, and the plan identifies the offending filename. Regressions reproduce the previous unsafe acceptance and verify that blocked writes preserve the original files. CSR JSON and Kubernetes YAML remain excluded from leaf inspection; explicit force overrides retain their documented behavior.
  • Managed-export, text-plan output, and existing-artifact failures now carry contextual error wrappers using %w. The closed-stdout regression verifies the original error remains available through errors.Is.

README, examples, architecture notes, and changelog match these changes. Full pre-commit checks (including race tests), generated docs, and Go language-server diagnostics pass. The required dependency hook also refreshed two transitive development dependencies.

Functional testing against the real certificate-management setup passed previews and isolated replacement writes: 15 replacements and 24 skips. The original tree and skipped bundle contents were unchanged; temporary private artifacts were removed. The intentional changeit default remains unchanged.

The existing Go 1.27 embedded-field comment still has the technical explanation and build evidence in its thread and remains open pending reviewer agreement, per the repository disagreement policy.

Copilot AI 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.

Copilot review overview

🔵 Needs a closer look

Five unresolved moderate findings remain in lock cleanup, stale-scope handling, and existing-artifact validation.

Review effort: Lite
Findings: 1 High severity

Open (1)
Files not reviewed (1)
  • web/package-lock.json: Generated file

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 19d2bad5c3

ℹ️ About Codex in GitHub

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

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

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

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

Comment thread internal/bundleplan.go
Comment thread internal/bundleplan_existing.go
Comment thread internal/bundleplan_existing.go Outdated
Validate metadata identity and filename lengths before replacement, including mixed-case artifacts. Preserve review decisions when scope changes and report lock cleanup failures without removing another refresh marker.
Copilot AI review requested due to automatic review settings September 22, 2026 12:53
@danielewood

Copy link
Copy Markdown
Collaborator Author

Fixed the latest three diff findings and the review-summary lock/scope concerns in e577951.

  • Planning enforces a 255-byte UTF-8 component limit for directories and generated artifacts. Short staging/backup prefixes allow valid long directory names to be written.
  • Existing certificate metadata requires nonempty certificate fields, and manifests require bundle identity plus selected leaf PEM. Empty/null/incomplete metadata blocks ordinary replacement, with the filename in the plan. Artifact extensions and CSR/Kubernetes exclusions are case-insensitive.
  • Refresh-lock cleanup now returns errors while preserving committed statuses. Lock ownership is checked before commit; cleanup uses the original open directory handle and preserves replacement markers, including if the output directory moves.
  • A scope conflict during writing marks pending entries blocked and invalidates the plan. Previously committed bundles retain their status, including when the conflict occurs while staging a later bundle.

Regression coverage includes the reported pre-fix failures, byte-length boundaries, preserved malformed/conflicting artifacts, lock cleanup/interference, stale-plan reuse, and partial-write reporting. README, examples, architecture notes, and changelog match the final behavior. Full pre-commit checks, race tests, generated docs, and Go language-server diagnostics pass. Required hooks refreshed the indirect Go dependency and web development lockfile.

Real-data checks against the certificate-management setup passed: 15 replacements and 24 skips in an isolated copy, original files unchanged, skipped directories preserved, and temporary private artifacts removed. The intentional changeit default is unchanged.

The existing Go 1.27 syntax disagreement remains open with its prior technical explanation and build evidence, pending reviewer agreement.

Copilot AI 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.

Copilot review overview

🔵 Needs a closer look

Resolve the moderate symlink-aware exclusion issue and address the requested review comments before approval.

Review effort: Lite
Findings: 1 High severity

Open (1)
Files not reviewed (1)
  • web/package-lock.json: Generated file

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e577951096

ℹ️ About Codex in GitHub

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

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

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

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

Comment thread internal/bundleplan.go Outdated
Comment thread internal/bundleplan.go Outdated
Keep staging, rename, and cleanup operations on open directory handles so output-root relocation cannot strand private keys. Treat failed reinspection as a blocked plan and canonicalize symlink-aware exclusions before scanning.
Copilot AI review requested due to automatic review settings September 22, 2026 13:16
@danielewood

Copy link
Copy Markdown
Collaborator Author

Fixed the follow-up review in dd84c2e, including the symlink-aware exclusion concern from the latest review overview.

The exclusion reproductions showed both directions of a working-directory alias bypass: relative exclusions with an absolute scan root, and absolute exclusions with a relative scan root. They also showed a declared future output under a symlinked ancestor being ingested when it appeared during the scan. Exclusions now resolve those aliases and missing suffixes, and ordinary in-root symlink inputs retain matching canonical boundaries.

The two new diff findings are also fixed: staging/writes/renames/rollback/cleanup use opened directory handles, and failed existing-bundle reinspection records a blocked validation result while preserving the underlying error. The relocated-output regression includes a staged synthetic private key and verifies cleanup cannot remove a replacement staging path or lock.

Full pre-commit checks, race tests, generated docs, and Go language-server diagnostics pass. The real certificate-management setup passed again: 15 isolated replacements and 24 skips, original tree and skipped bundles unchanged, temporary private artifacts removed. README, examples, architecture notes, and changelog describe the final behavior. The intentional changeit default remains unchanged.

The previously explained Go 1.27 syntax disagreement remains open pending reviewer agreement.

Copilot AI 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.

Copilot review overview

🟡 Changes recommended

The critical and moderate findings remain unresolved.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 2 High severity

Open (2)
Files not reviewed (1)
  • web/package-lock.json: Generated file

Comment thread internal/bundleplan.go
Comment on lines +176 to +183
for _, name := range append(slices.Clone(names), input.RequireBundles...) {
if _, ok := rules[name]; !ok {
return nil, fmt.Errorf("%w: bundle %q has no configuration rule", errBundlePlanInput, name)
}
}
for _, name := range input.RequireBundles {
if !slices.Contains(names, name) {
return nil, fmt.Errorf("%w: required bundle %q is outside the selected scope", errBundlePlanInput, name)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I could not reproduce this finding: append(slices.Clone(names), input.RequireBundles...) is used only to validate rule existence and never assigned back to names. The selected scope is unchanged, and the following out-of-scope check remains reachable. Commit 138394e adds TestBundlePlan_RequiredBundlesRespectScope covering rejection of required-but-unselected bundles without any output, successful required names inside the scope, unscoped requirements, and unknown rules. The scope behavior already passed before the production fixes. I added a clarifying comment and am leaving this disagreement open for reviewer confirmation.

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: dd84c2e7cf

ℹ️ About Codex in GitHub

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

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

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

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

Comment thread internal/bundleplan.go
Comment thread internal/bundleplan.go
Recheck the reviewed directory and lock after staging the manifest and immediately before replacement. Preserve blocked and committed states when safety checks fail, and cover required bundles outside an explicit scope.
Copilot AI review requested due to automatic review settings September 22, 2026 13:44
@danielewood

danielewood commented Sep 22, 2026 •

Copy link
Copy Markdown
Collaborator Author

Addressed the latest review findings in 138394e:

  • Added a final commit guard after manifest staging, immediately before the first rename, checking the opened parent against the reviewed destination and rechecking lock ownership and the other safety conditions.
  • Destination and lock failures now mark pending bundles blocked and invalidate the plan, while preserving already committed statuses and underlying errors.
  • Added regression coverage for artifact/manifest interference, partial replacements, and required bundles outside an explicit scope. The scoped-export finding is a disagreement: required-rule validation appends to a clone and does not expand the export scope.

Validation: pre-commit run --all-files and gopls check passed. The real-certificate functional check replaced 15 bundles in an isolated copy and left 24 skipped bundles unchanged; the original input/setup tree was verified unchanged and temporary private artifacts were removed. The required dependency hook also refreshed one transitive web development dependency.

The two fixed threads are resolved. The scoped-export and Go-version disagreements remain open with explanations. CI passed for this commit. Automated rereview is still running.

Copilot AI 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.

Copilot review overview

🟡 Changes recommended

One or more issues must be addressed before approval.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 4 High severity

Open (4)
Files not reviewed (1)
  • web/package-lock.json: Generated file

Comment thread internal/bundlepaths.go
Comment on lines +133 to +143
info, err := os.Lstat(d.path)
if err != nil {
return fmt.Errorf("checking created bundle output: %w", err)
}
if !info.IsDir() {
return fmt.Errorf("%w: created bundle output must be a directory", ErrBundlePlanBlocked)
}
if err := d.check(); err != nil {
return err
}
d.ancestor, d.identity = d.path, info
Comment thread internal/bundleplan.go
Comment on lines +343 to +344
if len(p.writes) == 0 {
return nil
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants