Skip to content

πŸ› fix(v1.6): remediate comprehensive review findings#574

Merged
scttbnsn merged 7 commits into
dev/v1.6from
fix/v1.6-review-remediation
Jul 21, 2026
Merged

πŸ› fix(v1.6): remediate comprehensive review findings#574
scttbnsn merged 7 commits into
dev/v1.6from
fix/v1.6-review-remediation

Conversation

@scttbnsn

@scttbnsn scttbnsn commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Summary

Once merged, the existing dev/v1.6 β†’ main release PR #572 will automatically update to this remediated tree.

Verification

  • app: 12,287 tests across 392 files; 100% statements, branches, functions, and lines
  • UI: 4,273 tests across 213 files; 100% statements, branches, functions, and lines
  • workflow tests: 39 tests across 9 files
  • root release/docs scripts: 107 tests
  • demo behavioral/security tests: 5 tests; build green
  • app and UI production builds green
  • UI typecheck green
  • actionlint green
  • zizmor: no findings (offline mode; configured suppressions reported)
  • repository pre-push policy gate green in full

Release handling

This is the complete remediation path for v1.6. Do not merge #572 until this PR is integrated and its updated candidate has completed the required exact-SHA acceptance window.

Changelog

  • ✨ Added demo contract/security test scripts and made demo contract + production build first-class CI gates.
  • ✨ Added release-candidate/GA promotion inputs and end-to-end release evidence checks for exact-SHA acceptance.
  • ✨ Added OpenAPI update-gating models (UpdateBlocker, UpdateEligibility) and exposed ContainerResource.tagPinGated + updateEligibility.
  • ✨ Added digest-cache poll-cycle β€œgeneration/handle” plumbing across registries to prevent cross-cycle invalidation.
  • ✨ Added contract tests for release workflow wiring (demo build gates; release-cut retry naming; digest/tag propagation; recoverable finalization ordering).
  • πŸ”§ Changed release-cut to β€œstage first, finalize last” with idempotent, digest-validated, recoverable GA finalization (candidate digest matching + exact image digest publishing + draft/public guards).
  • πŸ”§ Changed preview error actions from { label, href } to typed { code, href } (API, OpenAPI schemas, UI normalization, i18n presentation).
  • πŸ”§ Changed authentication/upgrades documentation to consistently describe fail-closed behavior (protected routes: 401; /health: 503; discovery/status remains public).
  • πŸ”§ Changed SSE client lifecycle to track/route events only from the active stream (and ignore late events after stop).
  • πŸ”§ Changed container candidate identity logic to ignore suggestedTag, gate created identity changes to legacy (no-digest) cases, and apply watcher-scoped identity keys.
  • πŸ”§ Changed notification/template preview handling to prevent stale async results (generation invalidation) and updated MSW mocks to validate preview/persistence shapes.
  • πŸ› Fixed overlapping digest-cache poll cycle end behavior and registry end-handle correctness.
  • πŸ› Fixed preview race conditions across container/notification/template selection changes (stale results cannot overwrite newer state).
  • πŸ› Fixed SSE reconnection scheduling and teardown edge cases after stop.
  • πŸ› Fixed preview action consumer expectations in tests/UI to match the new typed code contract.
  • πŸ”’ Added/strengthened cross-registry digest verification and release integrity checks; restricted cosign/container signing and provenance/SBOM attestation to prereleases; tightened release artifact/source SHA handling.
  • ⚠️ Breaking: preview error/action consumers must migrate from action.label to action.code (open-registry-settings / open-trigger-settings).
  • ⚠️ Breaking: internal registry/digest-cache lifecycle APIs now use return/accept β€œhandle/generation” values (signature/behavior changes in lifecycle helpers).

Concerns

  • Validate all downstream integrations/tests are migrated from action.label to action.code (including any non-covered UI paths).
  • Confirm GA-only release-cut dispatch inputs (candidate_tag, candidate_digest) and β€œexact seven-day-old prerelease RC candidate” logic match the intended release policy end-to-end.
  • Ensure release finalization remains idempotent when re-dispatched mid-run (tag exists vs force-update; draft/public transitions; digest re-checks).
  • Check for any remaining stale-preview race paths not using the new generation/invalidation guards.
  • Review whether any memory/resource cleanup is needed for tracked SSE stream instances and digest-cache cycles on early exits/errors.
  • Verify notification preview mock behavior continues to match production contracts (template override validation + rendered field expectations).

scttbnsn added 5 commits July 21, 2026 10:10
…#566

The display-honesty batch changed two surfaces these specs asserted:

- #406: the one-clock maturity panel collapsed the countdown into a
  single '{countdown} Β· unlocks {date}' line, replacing 'Lifts at'.
- #498: insight-only cards read 'Current' (pinned left the Update
  column) and the insight-kind badge was retired; pinned-ness is the
  persistent pin glyph on the Tag cell, asserted in both table and
  cards. Fixture now sets tagPinGated, the backend gate verdict the
  glyph keys on.

Verified locally: 4 passed against the QA env.
@vercel

vercel Bot commented Jul 21, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
drydock-website Ready Ready Preview, Comment Jul 21, 2026 8:19pm
drydockdemo-website Ready Ready Preview, Comment Jul 21, 2026 8:19pm

@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@scttbnsn, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 27 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
βš™οΈ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: e9be5679-e749-4ea7-a175-8600cd343178

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between f379d3d and c20eceb.

πŸ“’ Files selected for processing (2)
  • .github/tests/release-cut-retry-workflow.test.ts
  • apps/demo/src/mocks/handlers.contract.test.ts
πŸ“ Walkthrough

Walkthrough

The PR adds demo contract tests and CI build gates, converts release-cut to a recoverable digest-validated pipeline, introduces typed preview actions and update-eligibility schemas, hardens SSE and digest-cache lifecycle handling, updates candidate identity detection, clarifies authentication and support documentation, and prevents stale asynchronous preview results in the UI.

Possibly related PRs

πŸš₯ Pre-merge checks | βœ… 2
βœ… Passed checks (2 passed)
Check name Status Explanation
Linked Issues check βœ… Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check βœ… Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
πŸ§ͺ Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/v1.6-review-remediation

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❀️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai 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.

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
app/agent/AgentClient.ts (1)

881-897: 🎯 Functional Correctness | 🟠 Major | ⚑ Quick win

Guard queued SSE parsing before it mutates state.

A data event can pass Line 882, enqueue work, then stop() clears the stream before the queued callback runs. That callback still parses and dispatches stale events after shutdown.

Proposed fix
       sseProcessing = sseProcessing
         .then(async () => {
+          if (this.stopped || this.activeSseStream !== stream) {
+            return;
+          }
           buffer += decodedChunk;
           buffer = await this.processSseBuffer(buffer);
         })

Update the stop test to emit data immediately before stop() and assert handleEvent remains untouched.

πŸ€– Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/agent/AgentClient.ts` around lines 881 - 897, Guard the queued callback
in the SSE processing chain, not only the stream data handler: before appending
to buffer or calling processSseBuffer, verify the client is not stopped and
activeSseStream is still stream. Update the stop test to emit data immediately
before stop() and assert handleEvent is not called.
🧹 Nitpick comments (1)
.github/workflows/release-cut.yml (1)

394-398: πŸ“ Maintainability & Code Quality | πŸ”΅ Trivial | βš–οΈ Poor tradeoff

Registry list duplicated across 5 sites β€” extract to job-level env to prevent divergence.

docker.io/codeswhat/drydock and quay.io/codeswhat/drydock are repeated in meta (359-362), staging_meta (377-380), candidate_refs (394-398), source_candidates (448-452), and image_refs (504-506). If a registry is added to meta but missed here, its GA digest silently goes unvalidated. Hoist the repo names into job-level env and reference them everywhere.

+    env:
+      DOCKERHUB_REPO: docker.io/codeswhat/drydock
+      QUAY_REPO: quay.io/codeswhat/drydock

Then use "${DOCKERHUB_REPO}:${CANDIDATE_TAG#v}" / "${QUAY_REPO}:${CANDIDATE_TAG#v}" in the bash arrays.

πŸ€– Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/release-cut.yml around lines 394 - 398, Move the shared
Docker Hub and Quay repository names into job-level env variables, then update
the meta, staging_meta, candidate_refs, source_candidates, and image_refs
definitions to reference those variables consistently. In the candidate_refs
bash array, use DOCKERHUB_REPO and QUAY_REPO with CANDIDATE_TAG while preserving
the existing GHCR entry.
πŸ€– Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/demo/src/mocks/handlers/notifications.ts`:
- Around line 124-132: Add shared JSON-record validation for the handlers in
apps/demo/src/mocks/handlers/notifications.ts (lines 124-132 and 95-121) and
apps/demo/src/mocks/handlers/settings.ts (lines 8-20), returning 400 for parse
failures, null, arrays, or other non-object bodies before reading fields. In the
notification PATCH handler, validate and construct an update containing only
allowed NotificationRuleUpdate fields, then have Object.assign use that update
rather than the raw body so id and arbitrary properties cannot be changed.

In `@e2e/playwright/v16-modes-pins.spec.ts`:
- Line 176: Update the ContainerFixture interface to declare the optional
tagPinGated?: boolean property, so the assignment in the fixture setup is
type-safe.

In `@scripts/release-docs-identity.test.mjs`:
- Around line 349-351: Update both authentication assertions around the visible
doesNotMatch checks to use one shared regex that matches broad-401 wording with
all or every, singular or plural call/request, and either β€œreturn `401`” or β€œare
rejected with `401`” phrasing. Reuse the same pattern in both assertion
locations instead of maintaining separate coverage.
- Around line 411-418: Update the generic latest-row assertion in the security
policy test to match the `latest` token case-insensitively while preserving
flexible whitespace around it, so variants such as `| Latest |` are rejected.
Keep the existing assertions in the `security policy distinguishes stable and
prerelease support` test unchanged.

In `@ui/tests/views/NotificationsView.spec.ts`:
- Around line 366-374: Update the trigger transition test around the preview
button and triggerSelect interactions so the initial draft uses Discord, then
change the selection to Slack before asserting the preview button is enabled.
Ensure the first preview request is started with trigger:discord-alerts and the
subsequent setValue switches to trigger:slack-alerts, preserving the existing
assertions and click flow.

---

Outside diff comments:
In `@app/agent/AgentClient.ts`:
- Around line 881-897: Guard the queued callback in the SSE processing chain,
not only the stream data handler: before appending to buffer or calling
processSseBuffer, verify the client is not stopped and activeSseStream is still
stream. Update the stop test to emit data immediately before stop() and assert
handleEvent is not called.

---

Nitpick comments:
In @.github/workflows/release-cut.yml:
- Around line 394-398: Move the shared Docker Hub and Quay repository names into
job-level env variables, then update the meta, staging_meta, candidate_refs,
source_candidates, and image_refs definitions to reference those variables
consistently. In the candidate_refs bash array, use DOCKERHUB_REPO and QUAY_REPO
with CANDIDATE_TAG while preserving the existing GHCR entry.
πŸͺ„ Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
βš™οΈ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 0907b193-719d-4015-afb4-f60e99948578

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between bfddb0b and d88fd03.

β›” Files ignored due to path filters (2)
  • CHANGELOG.md is excluded by !CHANGELOG.md
  • apps/demo/package-lock.json is excluded by !**/package-lock.json, !**/package-lock.json
πŸ“’ Files selected for processing (39)
  • .github/tests/ci-verify-workflow.test.ts
  • .github/tests/release-cut-retry-workflow.test.ts
  • .github/workflows/ci-verify.yml
  • .github/workflows/release-cut.yml
  • DEPRECATIONS.md
  • README.md
  • SECURITY.md
  • app/agent/AgentClient.test.ts
  • app/agent/AgentClient.ts
  • app/api/openapi.test.ts
  • app/api/openapi/schemas.test.ts
  • app/api/openapi/schemas.ts
  • app/api/preview-errors.test.ts
  • app/api/preview-errors.ts
  • app/api/preview.test.ts
  • app/model/container.ts
  • app/registries/BaseRegistry.test.ts
  • app/registries/BaseRegistry.ts
  • app/store/container.test.ts
  • app/watchers/providers/docker/Docker.ts
  • app/watchers/providers/docker/digest-cache-lifecycle.test.ts
  • app/watchers/providers/docker/digest-cache-lifecycle.ts
  • apps/demo/package.json
  • apps/demo/src/mocks/data/notifications.ts
  • apps/demo/src/mocks/handlers.contract.test.ts
  • apps/demo/src/mocks/handlers/notifications.ts
  • apps/demo/src/mocks/handlers/settings.ts
  • content/docs/current/configuration/authentications/index.mdx
  • e2e/playwright/v16-modes-pins.spec.ts
  • scripts/release-docs-identity.test.mjs
  • ui/src/components/DataTableColumnPicker.vue
  • ui/src/locales/en/containerComponents.json
  • ui/src/services/preview.ts
  • ui/src/views/NotificationsView.vue
  • ui/src/views/containers/useContainerPreview.ts
  • ui/tests/components/DataTableColumnPicker.spec.ts
  • ui/tests/services/preview.spec.ts
  • ui/tests/views/NotificationsView.spec.ts
  • ui/tests/views/containers/useContainerActions.spec.ts

Comment thread apps/demo/src/mocks/handlers/notifications.ts
Comment thread e2e/playwright/v16-modes-pins.spec.ts
Comment thread scripts/release-docs-identity.test.mjs Outdated
Comment thread scripts/release-docs-identity.test.mjs
Comment thread ui/tests/views/NotificationsView.spec.ts

@coderabbitai coderabbitai 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.

🧹 Nitpick comments (2)
apps/demo/src/mocks/handlers.contract.test.ts (1)

43-57: πŸ—„οΈ Data Integrity & Integration | πŸ”΅ Trivial | ⚑ Quick win

Verify the sanitized rule is not persisted.

This assertion checks only the PATCH response. Read the rule back through the GET endpoint and assert that arbitrary and the rewritten id are absent there too; otherwise a handler could sanitize the response while retaining invalid fields in mock state.

πŸ€– Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/demo/src/mocks/handlers.contract.test.ts` around lines 43 - 57, Extend
the notification update test around the PATCH request and response to fetch the
updated rule through the GET endpoint, then assert the persisted result does not
contain the rewritten id or arbitrary field. Keep the existing response
assertions and use the GET result to verify mock state was sanitized rather than
only the returned payload.
.github/tests/release-cut-retry-workflow.test.ts (1)

147-177: πŸ“ Maintainability & Code Quality | πŸ”΅ Trivial | ⚑ Quick win

Reject hardcoded registry duplicates.

These assertions prove that environment-backed references exist, but not that hardcoded docker.io/... or quay.io/... references were removed. A duplicate can therefore pass this test while violating the β€œonce at job scope” contract. Add negative assertions over loadReleaseSteps() or assert the exact reference fields.

Proposed test addition
   expect(releaseJob?.env).toMatchObject({
     DOCKERHUB_REPO: 'docker.io/codeswhat/drydock',
     QUAY_REPO: 'quay.io/codeswhat/drydock',
   });
+  const releaseStepText = JSON.stringify(loadReleaseSteps());
+  expect(releaseStepText).not.toContain('docker.io/codeswhat/drydock');
+  expect(releaseStepText).not.toContain('quay.io/codeswhat/drydock');
πŸ€– Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/tests/release-cut-retry-workflow.test.ts around lines 147 - 177, The
release registry test only verifies environment-backed references and must also
reject duplicate hardcoded registry URLs. Extend the test around
loadReleaseSteps and the existing releaseJob assertions to assert that step
commands and relevant fields do not contain hardcoded
docker.io/codeswhat/drydock or quay.io/codeswhat/drydock references, while
preserving the job-scope env and env-variable usage checks.
πŸ€– Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In @.github/tests/release-cut-retry-workflow.test.ts:
- Around line 147-177: The release registry test only verifies
environment-backed references and must also reject duplicate hardcoded registry
URLs. Extend the test around loadReleaseSteps and the existing releaseJob
assertions to assert that step commands and relevant fields do not contain
hardcoded docker.io/codeswhat/drydock or quay.io/codeswhat/drydock references,
while preserving the job-scope env and env-variable usage checks.

In `@apps/demo/src/mocks/handlers.contract.test.ts`:
- Around line 43-57: Extend the notification update test around the PATCH
request and response to fetch the updated rule through the GET endpoint, then
assert the persisted result does not contain the rewritten id or arbitrary
field. Keep the existing response assertions and use the GET result to verify
mock state was sanitized rather than only the returned payload.

ℹ️ Review info
βš™οΈ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 4b1d533e-8dbb-48a4-9542-19fcf5aeaeb7

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between d88fd03 and f379d3d.

πŸ“’ Files selected for processing (10)
  • .github/tests/release-cut-retry-workflow.test.ts
  • .github/workflows/release-cut.yml
  • app/agent/AgentClient.test.ts
  • app/agent/AgentClient.ts
  • apps/demo/src/mocks/handlers.contract.test.ts
  • apps/demo/src/mocks/handlers/json.ts
  • apps/demo/src/mocks/handlers/notifications.ts
  • apps/demo/src/mocks/handlers/settings.ts
  • e2e/playwright/v16-modes-pins.spec.ts
  • scripts/release-docs-identity.test.mjs
🚧 Files skipped from review as they are similar to previous changes (7)
  • apps/demo/src/mocks/handlers/settings.ts
  • scripts/release-docs-identity.test.mjs
  • e2e/playwright/v16-modes-pins.spec.ts
  • apps/demo/src/mocks/handlers/notifications.ts
  • app/agent/AgentClient.test.ts
  • app/agent/AgentClient.ts
  • .github/workflows/release-cut.yml

@scttbnsn
scttbnsn merged commit 392d09a into dev/v1.6 Jul 21, 2026
5 checks passed
@scttbnsn
scttbnsn deleted the fix/v1.6-review-remediation branch July 21, 2026 20:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant