Skip to content

πŸš€ release(v1.5.1-rc.3): intermediate release notes, i18n re-sync, web shell + renovate#459

Merged
scttbnsn merged 33 commits into
mainfrom
release/v1.5.1-rc.3
Jun 28, 2026
Merged

πŸš€ release(v1.5.1-rc.3): intermediate release notes, i18n re-sync, web shell + renovate#459
scttbnsn merged 33 commits into
mainfrom
release/v1.5.1-rc.3

Conversation

@scttbnsn

@scttbnsn scttbnsn commented Jun 28, 2026

Copy link
Copy Markdown
Contributor

This RC consolidates four streams of held work plus the docs/build fixes they surfaced. One branch, one PR, one cut.

Release notes β€” intermediate range (#452, #453)

  • New GET /api/containers/{id}/intermediate-release-notes endpoint, lazy-loaded when the popover opens β€” not embedded in the container model or agent snapshot, so it adds no ongoing payload weight. Accepts from (required) and to (defaults to the pending update tag).
  • The release-notes popover now shows the full range between the running and target version. Best-effort, semver-only; date/rolling tags (latest, stable) fall back to the two-panel current/target view. Cap via DD_RELEASE_NOTES_MAX_INTERMEDIATE (default 20, 0 disables); __FILE secret-file convention supported. Over the cap, the popover shows a non-silent "N older releases not shown" notice.
  • DD_RELEASE_NOTES_GITHUB_TOKEN is now forwarded to repos resolved from a dd.source.repo container label or persisted container.sourceRepo. The GHCR token fallback stays restricted to trusted sources (OCI labels, GHCR image paths) and is never sent to a container-label source. A warn line fires each watch cycle when a dd.source.repo label shadows a trusted OCI source label.
  • Three-tier cache with a hardened intermediate-range caching contract.

i18n / Crowdin re-sync (supersedes #458)

  • Re-synced the 16 target-locale containerComponents.json catalogs from Crowdin so key order tracks the English source.
  • Guard test asserting on-disk locale dirs match SUPPORTED_LOCALES.

CodesWhat web shell β€” apps/web

  • fumadocs v15 (mdx 15, core/ui 16.10), Next 16.2.9, React 19.2.7, Tailwind 4.3.1.
  • Moved app/lib/components into src/ to match the shared shell architecture; promoted lab section components to flat src/components.
  • src/lib/site-config.ts is the single reskin point; all brand couplings wired to it. Comparison scaffold made product-agnostic.
  • Whale OG share image (1200Γ—630) + regenerated favicon suite from the new headshot; config-driven version badge, manifest icon purpose + theme_color.
  • a11y fixes for site chrome, dead-code purge, sync-docs made portable + atomic (stops mutating the source tree).
  • Block-formatted the release-notes Callout in the watchers docs so fumadocs v15 builds.

Renovate (supersedes #460)

  • Adopt the shared CodesWhat Renovate preset.

Gate

Full pre-push gate green: biome, qlty, qlty-smells, coverage (app + ui, 100%), build, e2e, playwright, zizmor. apps/web build verified green through the real sync:docs path.

Closes #452, #453. Supersedes #458 and #460 (closed in favor of this consolidated RC).

crowdin-bot and others added 4 commits June 28, 2026 10:40
Re-syncs the 16 target-locale containerComponents.json catalogs and
normalizes their key order to match the English source. Generated by
the Crowdin sync workflow (run 28319493351).
Guards against locale-directory drift under ui/src/locales/. A recent
Crowdin misconfiguration wrote a stray en-US/ directory that only
surfaced in a sync PR; this fails CI fast if the on-disk locale set ever
diverges from SUPPORTED_LOCALES (extra or missing locale).
@vercel

vercel Bot commented Jun 28, 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 Jun 28, 2026 7:09pm
drydockdemo-website Ready Ready Preview, Comment Jun 28, 2026 7:09pm

scttbnsn added 24 commits June 28, 2026 07:09
…oundary

The OIDC authorization_endpoint, rate-limit peer-keying, and HTTP-trigger
proxy-scheme changes shipped in 1.4.6 and persist through all of 1.5, so
anyone updating from a pre-1.4.6 release hits them no matter which current
version they land on. Reworded the README warning + UPGRADE-NOTES lead so a
user who skipped 1.4.6 (e.g. 1.4.3 -> 1.5.1) doesn't assume they're exempt.
…16.2.9

- loader() to v15 positional form in lib/source.ts
- docs page imports canonical fumadocs-ui/page (matches target shell)
- drop dead fumadocs-mdx:collections/* tsconfig alias
- aligns apps/web with sockguard/portwing shell architecture

Part of CodesWhat shared shell extraction (Phase A).
- react/react-dom 19.2.7, tailwindcss + @tailwindcss/postcss 4.3.1
- tailwind-merge 3.6, lefthook 2.1.9, @types/* latest
- align @biomejs/biome to root 2.4.16 (shared biome.json $schema), not 2.5.x
- @types/node held at 25.x to match the Node 24 runtime

Part of CodesWhat shared shell extraction.
Single source of truth for site identity (name, repo slug, domain, logo,
demo url, docker image, twitter, aurora palette, storage prefix) plus
derived BASE_URL/GITHUB_URL/DEMO_URL/DOCKER_HUB_URL/REPO_SLUG helpers.

Wired ~50 call sites across 17 files (app routes metadata + JSON-LD,
chrome components, lab components, comparison-route) to import from it.
Resolved runtime values unchanged β€” de-duplication only. MarketingShell
gains an optional aurora prop defaulting to SITE_CONFIG.aurora.

This is the per-site re-skin point for the shared CodesWhat shell.
Part of CodesWhat shared shell extraction (Phase B).
- starhistory: star-history.com chart URLs now use REPO_SLUG (were raw CodesWhat/drydock)
- footer: visible brand span -> SITE_CONFIG.name; logo alt -> "" (decorative, matches header)
- demo: share payload pinned to SITE_CONFIG.demoUrl (production, not env preview); share/iframe titles -> SITE_CONFIG.name
- compare-variants: cellValue map key + eyebrow -> SITE_CONFIG.name
- wire logoInvertOnDark at header/footer/hero logo sites (field was inert)

Part of CodesWhat shared shell extraction (Phase B review pass).
- remove Drydock-specific FAQ JSON-LD from the docs renderer (was a
  coupling trap, incomplete β€” 1 of ~40 Qs β€” and FAQ rich results are
  no longer shown for non-gov/health sites); keep BreadcrumbList JSON-LD
- delete now-dead lib/docs-faq-route.ts + its (non-running) test
- typed docs data via getDocsPage/DocsPageData (drops page.data as any);
  this surfaced + fixed a latent MdxImage prop-variance bug
- docs metadata: BASE_URL/SITE_CONFIG, twitter card summary_large_image, twitter.creator
- root layout: title template '%s | Drydock' + default; docs tabs/Google
  now show 'Title | Drydock' instead of bare titles
- compare/security/comparison-route titles use { absolute } to opt out of
  the template (they already carry the brand) β€” verified no double-branding
- og image + locale sourced from SITE_CONFIG

Part of CodesWhat shared shell extraction (Phase C).
…ecture

Relocate the Next.js App Router tree under src/ so apps/web matches the
canonical CodesWhat shell layout (sockguard's architecture). No behavior
change β€” every move is a git rename.

- πŸ”„ refactor(web): git mv app/ lib/ components/ β†’ src/
- πŸ”§ config(web): drop deprecated tsconfig baseUrl (TS6 TS5101); paths
  resolve relative to tsconfig dir, "@/*" β†’ "./src/*"
- πŸ”§ config(root): repoint biome globals.css ignore to src/app/globals.css
- βœ… test(web): update compare-pages helper test paths to src/

Gate: type-check βœ“ lint βœ“ build βœ“ test:scripts βœ“ (240+ docs routes prerender)
Move the 9 chosen homepage/footer sections out of the exploration
src/components/lab/ folder into flat src/components/ with clean names,
matching the shell's flat component convention. Drops the leftover
"-variants"/lab scaffolding from the design-exploration phase.

- hero-variants→hero (Hero), features-variants→features (Features),
  compare-variants→compare-section (CompareSection), demo-variants→demo (Demo),
  ecosystem-variants→ecosystem (Ecosystem), roadmap-variants→roadmap (Roadmap),
  starhistory-variants→star-history (StarHistory),
  getstarted-secure-toggle→get-started (GetStarted),
  footer-variants→footer (Footer)
- update importers: app/page.tsx, docs-shell.tsx, marketing-shell.tsx
- remove now-empty src/components/lab/

Gate: type-check + lint + build + test:scripts all green.
- add skip-to-content link + id="main-content" to DocsShell (mirrors
  MarketingShell; fumadocs nav is disabled so its built-in skip link
  was suppressed)
- add focus-visible rings to nav links, icon buttons, and ThemeToggle
- ThemeToggle aria-label now reflects the action (Switch to light/dark)
- extract navLinkCn/iconButtonCn to src/lib/class-names.ts; site-header
  and footer import them instead of duplicating the strings

Gate: type-check + lint + build + test:scripts green.
…elf)

The comparison-route/comparison-page scaffold baked "drydock" into the
ComparisonRow field, verdict enum, and badge prop, so a sibling site
copying the scaffold would carry Drydock's identity at the type level.
Rename to the agnostic `self`:

- ComparisonRow.drydock β†’ .self; verdict "drydock" β†’ "self"
- drydockBadge prop/const/className β†’ selfBadge
- pipe-table verdict column values drydock β†’ self across all competitors
- CTA "Ready to try Drydock?" now derives from SITE_CONFIG.name

Per-competitor content stays Drydock-flavored; only the reusable type
surface and enum became agnostic. Gate: type-check+lint+build+scripts green.
… slugs

- extract ComparisonCellIcon (yes/partial/no) to one component used by
  compare-matrix and compare-section; reconcile the drifted "No" color
- icon SVGs are aria-hidden with sr-only state text (bare-SVG aria-label
  is unreliable in JAWS+Chrome)
- sitemap compare list now derives from getComparisonRouteSlugs() instead
  of a hardcoded array, so new compare pages can't drift out of the sitemap

Gate: type-check + lint + build + test:scripts green (all 9 compare routes).
…hRange

- πŸ› #452: the dedicated DD_RELEASE_NOTES_GITHUB_TOKEN is now forwarded even
  for untrusted source repos (dd.source.repo container label / persisted
  container.sourceRepo). The GHCR PAT fallback stays gated by trust, so the
  broadly-scoped credential is never sent to an attacker-controllable repo.
- ✨ #453: GithubProvider.fetchRange enumerates releases in (current, target]
  via the paginated /releases endpoint, strict-semver ordered newest-first
  (date/rolling tags fall back), each page through withRetry, 10-page cap.
- βœ… 64 provider tests, GithubProvider.ts at 100% coverage.

Refs #452, #453
… tooling

- delete nine identical passthrough src/app/compare/*/layout.tsx (App
  Router applies the parent layout; they add zero behavior)
- delete unused AnnouncementBanner component (no importers)
- delete historical migrate-docs.mjs + migrate-docs.test.mjs (Docsify
  migration is complete; it reads a ../../docs/ tree that no longer exists)

Gate: type-check + lint + build + test:scripts green (all 9 compare routes intact).
…e_color

- add SITE_CONFIG.version; Hero badge reads it instead of a hardcoded
  "v1.5.0" string that staled every release
- web manifest icons use "any maskable" so non-maskable environments get
  a usable icon; theme_color aligned to #0a0a0a (matches viewport dark)
- add globals.d.ts ambient CSS shims (TS6 noUncheckedSideEffectImports)

Gate: type-check + lint + build + test:scripts green.
- guard the root CHANGELOG.md read (DD_CHANGELOG_PATH override); a sibling
  site without one now logs a warning and skips instead of crashing the build
- write the generated changelog into the build target under the active
  version slug instead of into content/docs/current/ β€” no more source-tree
  mutation as a build side-effect
- build into content/docs.tmp and renameSync into place so a mid-run crash
  can't leave a blank content/docs/ (and thus a blank docs site)
- update content/docs/README.md to describe the actual sync pipeline

Gate: build (runs sync:docs) + type-check + lint + test:scripts green;
changelog renders under /docs/v1.5; missing-CHANGELOG path verified non-fatal.
… orchestration

- πŸ› #452: cache key is now three-tier (#auth / #token / #anon) so an untrusted
  source fetched WITH the dedicated token no longer poisons the anonymous bucket
  now that the token is forwarded to untrusted sources.
- πŸ› #452: warn when a dd.source.repo container label shadows a trusted image
  source label (silent trusted→untrusted downgrade that drops the GHCR fallback).
- ✨ #453: getIntermediateReleaseNotes orchestrates a cached, capped range fetch
  (DD_RELEASE_NOTES_MAX_INTERMEDIATE, default 20, 0 disables; cap applied at read
  time with a non-silent hiddenCount; interrupted fetches are not cached).
- βœ… 131 release-notes tests, index.ts + GithubProvider.ts at 100% coverage.

Refs #452, #453
Lazy-load endpoint backing #453. `from` (current tag) is required; `to`
defaults to the container's pending update tag (422 if neither is available).
Returns { releaseNotes, hiddenCount } β€” an empty list is valid, never a 404 β€”
so intermediate notes stay off the container model and the agent SSE snapshot,
keeping that payload bounded. OpenAPI documented; handler at 100% coverage.

Refs #453
ReleaseNotesLink now fetches the releases between a container's current and
target tag on demand (popover open / inline mount) from the new endpoint, and
renders them newest-first as collapsible rows with a non-silent
"N older releases not shown" indicator. Notes stay off the container model, so
the list never weighs down the container payload or the agent snapshot.

- export normalizeReleaseNotes for reuse by the new service call
- getContainerIntermediateReleaseNotes service wrapper (404 β†’ null, maps +
  validates each note through normalizeReleaseNotes)
- 3 new i18n keys across all 17 locales (en source; Crowdin localizes later)
- wired container-id/from-tag/to-tag through the container + dashboard callers
  (security views aggregate across containers, left on the two-panel view)
- full ui suite 3661 tests, 100% coverage

Refs #453
…452, #453)

- watcher docs: the DD_RELEASE_NOTES_GITHUB_TOKEN trust override with narrow
  PAT-scoping guidance, a warn callout for the dd.source.repo silent downgrade,
  and the intermediate release notes feature + DD_RELEASE_NOTES_MAX_INTERMEDIATE
- ghcr docs: clarify the GHCR fallback is trusted-sources-only
- CHANGELOG [1.5.1-rc.3] entries for both issues

Refs #452, #453
Extends local>CodesWhat/.github:renovate-config for org-wide policy
(14-day soak, internalChecksFilter strict, config:best-practices).
Keeps drydock's npm-per-workspace + Playwright groupings, the
Playwright Docker custom manager, and the patch-only GitHub Actions
auto-merge rule (enforced by app/renovate-config.test.ts).
Adversarial review of the #452/#453 implementation surfaced two
high-severity caching bugs that 100% coverage masked (tests matched the
buggy behavior):

- πŸ› fix(release-notes): mark cooldown short-circuit as interrupted so the
  empty range result is not cached as complete for the 1h TTL, matching
  fetchByTag's undefined-on-cooldown contract
- πŸ› fix(release-notes): mark page-cap exhaustion (all 10 pages full) as
  interrupted so a truncated range is never cached as the full set
- πŸ› fix(release-notes): normalize from/to tags (trim, strip v-prefix,
  lowercase) in the intermediate cache key so v1.2.0 and 1.2.0 share a slot
- πŸ› fix(ui): gate intermediate-notes fetch on hasStructuredNotes so the
  link never lazy-loads a range it cannot render
- πŸ“ chore(release-notes): debug-log when DD_RELEASE_NOTES_GITHUB_TOKEN is
  forwarded to an untrusted source in the range path (audit parity)
- βœ… test: cover #anon cache-bucket isolation and the interrupted contracts
scttbnsn added 4 commits June 28, 2026 14:14
The fumadocs v15 upgrade (this RC) is stricter about JSX in MDX: a
<Callout> whose content starts inline on the opening-tag line can't span
blank-line-separated paragraphs. The release-notes popover callout in the
watchers docs did exactly that, breaking the apps/web Turbopack build.
Move the open/close tags onto their own lines (block form) so the multi-
paragraph body parses. Rendered output is unchanged.
The release-notes feature commits predate this RC's biome 2.4.16 bump
(in the shell upgrade) and carried import-sort/format drift that the
newer biome flags. Apply the safe fixes so the root biome gate passes.
@scttbnsn scttbnsn changed the title πŸš€ release(v1.5.1-rc.3): Crowdin translation re-sync + locale-config guard test πŸš€ release(v1.5.1-rc.3): intermediate release notes, i18n re-sync, web shell + renovate Jun 28, 2026
@scttbnsn scttbnsn marked this pull request as ready for review June 28, 2026 18:36
Comment thread apps/web/src/components/github-badges.tsx Fixed

@biggest-littlest biggest-littlest 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.

RC consolidation looks clean β€” intermediate release-notes endpoint + UI, the Crowdin re-sync with the locale guard test, the fumadocs v15 web-shell move, and the renovate preset all accounted for, full gate green. LGTM.

ALARGECOMPANY
ALARGECOMPANY previously approved these changes Jun 28, 2026

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

Went through the four streams and the build/coverage/e2e gate. Scope matches the changelog, nothing dangling. Good to merge.

CodeQL js/incomplete-sanitization (high): `REPO_SLUG.replace("/", "%2F")`
only rewrites the first slash. REPO_SLUG has one slash today so the badge
URL is correct, but the single-occurrence replace is brittle and trips the
scanner. encodeURIComponent is a recognized sanitizer and encodes every
reserved char, so the URL stays correct for any owner/repo shape.

@biggest-littlest biggest-littlest 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.

Re-approving after the CodeQL sanitization fix β€” encodeURIComponent on the repo slug clears the incomplete-sanitization alert, badge URL unchanged for the real owner/repo. All required checks green.

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

Re-approve post-fix. CodeQL clean, full gate green, scope unchanged.

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.

Allow DD_RELEASE_NOTES_GITHUB_TOKEN to override source-repo "trust" for release-notes lookups (and document narrow scoping)

5 participants