Skip to content

Bring security/DESIGN.md under its 40 KiB budget and retire its ceiling - #4280

Merged
kriszyp merged 3 commits into
mainfrom
fix/security-design-doc-ceiling
Nov 11, 2026
Merged

kriszyp merged 3 commits into
mainfrom
fix/security-design-doc-ceiling

Conversation

@kriszyp

@kriszyp kriszyp commented Nov 11, 2026 •

Copy link
Copy Markdown
Member

⊙ Problem

Lint Source Code fails npm run check:design-docs on main because #4110 left security/DESIGN.md at 52,798 bytes, 30 bytes over its 52,768-byte ceiling. resources/DESIGN.md is also 3 bytes over its ceiling (45,886 / 45,883 after #4250), and resources/indexes/DESIGN.md has 22 bytes of headroom (91,898 / 91,920).

🤔 Condense across sections and retire the ceiling vs. pruning single sections?

PR CI runs check-design-docs.mjs --base HEAD^1: an edit to an over-ceiling file must cut it to 60% of its ceiling (31,660 bytes). No two sections hold that 21.1 KiB cut without dropping invariants. Condensing prose across sections reaches 31,613 bytes (9,347 bytes under the 40,960-byte budget); check-design-docs then requires retiring the spent ceiling.

💡 Solution

  • Tighten prose narration, duplicated allowlist statements, and code-level restatements across security/DESIGN.md, bringing it from 52,798 bytes to 31,613 bytes while keeping every invariant, residual risk, symbol, #issue reference, heading anchor, and named test pointer.
  • Run npm run check:design-docs -- --update-ceilings to retire "security/DESIGN.md" from build-tools/design-docs-ceilings.json, leaving 9,347 bytes of headroom under the 40 KiB budget.
  • Leave resources/DESIGN.md (-3 bytes headroom: 45,886 / 45,883) and resources/indexes/DESIGN.md (+22 bytes headroom: 91,898 / 91,920) untouched so they do not collide with active sibling PRs.
Section-by-section cuts in security/DESIGN.md (no invariants removed)
  • Header: Tightened the one-line summary while expanding Read this when: to cover newer security/ modules and keeping the root DESIGN.md index link.
  • OIDC trusted publishing: Condensed module-layout bullets into one paragraph, removed the npm trusted-publishing comparison aside, base64url 16-spelling arithmetic narration, and <component>-ci-deploy / deploy_source field enumerations already in source; kept claims.ts and all providers/ hooks, jwks.ts rate-limit separation, rejectToken sharing, per-audience memoization, generic.ts vs githubActionsProfile, all five invariants, hdb_oidc_token_use header.payload hashing and non-atomic rationale, deploy_source attestation (Record where a deploy came from: the commit, the CI run and the trust policy #3061), and harper deploy setup=true create-only/replicated hdb_oidc_trust rules.
  • Scoped tokens and synthetic-role identity: Condensed repeated REST/GraphQL allowlist prose, historical gate-1 handler-name fallback narration, and verbose rehydration wording; kept sub: 'scoped-operation' irrevocability and authExpiresAt eviction, the three known _scopedToken by-name sites plus future-site obligation, passwordless createTokens rejection, api_name/null registrations (get_backup, read_transaction_log, catchup), syntheticRoleName() hashing, 256-entry syntheticRolePermsMap LRU, and verifyPerms gate ordering.
  • TLS hot-reload & Self-signed renewal: Tightened multi-sentence watcher, reconciliation, and prepareSelfSignedCerts walkthroughs; kept main-only watching, 30 s/hourly incomplete-pair alarms, <=1/s chokidar trailing check, worker subscription reload, getPrivateKeys() refresh, from_config vs older-file guard, transient key-first/second-rotation mismatch note, transactional updateTLS last-good/CA-rebuild/zero-cert retention and 1.5s→5min backoff (A cert renewal whose table write misses the rebuild window downgrades TLS to the self-signed cert and never retries #2382), contextStorage.exit() and .ready recovery (harper-pro#1189), atomic publishSelfSignedCerts, <node>-self-signed naming, wx/0o600 key creation, and all named test cases.
  • Client-certificate revocation: Tightened sentence phrasing while keeping sourceContext.expiresAt + createCacheKey versioning, crl_next_update + gracePeriod retention, and separate-transaction CRL replacement + snapshot rules.
  • Component exports & JS/VM loaders (3 sections): Dropped the export { x } from './…' snippet, quoted load-error text, and prose repetition while keeping index.ts + getHarperExports parity, defining-module Symbol identity (markCredentialRejection), CommonJS-first resolveModule + PACKAGE_EXPORTS_RESOLVE digest tracking, loadSES ESM shims on Bun, all four VM entry points and gates, URL-keyed cjsCache/nativeModules, compile-only ESM retry, uncovered edges, and named test blocks.
  • Authentication, Session helpers & User/role lookups (3 sections): Removed transitional prose and GC measurement numbers (~1.8 KB); kept settleAuthFailure/rejectAuthenticationInPlace, markAuthenticationRejectedInPlace on WebSocket/MQTT upgrades, no credential fallthrough after deferred rejection, V8 CheckAssigningFunctionLiteralToProperty pretenuring rule, RocksDB user-version retry, LMDB turn-shared read txn, version-validated caches, onUserChange + userChangeNotificationEpoch() unchanged non-zero consumer guarantee and unaudited-table rule, and cloneUserView symbol provenance.
  • Component grants & PR previews (2 sections): Removed client-vs-server CLI walkthrough prose and hdb_preview_policy rejected-table aside; kept RESERVED_DATABASE_NAMES, pre-gate-2 finality, handler-aligned name resolution, origin-only constraint checks, deploy-only secret patterns, <app>-ci-preview + dual OIDC policies, preview: required / maxPreviews / maxTtlDays enforcement, serialized create-only enable (Set up GitHub Actions deploys with harper deploy setup=true provider=github-actions #3127), fence_preview_releases generation fencing + unfenced cases (A preview deploy already swapping, or applying on a peer, can go live after disable_previews #3613, A crash mid-swap or a canary restore can put a revoked preview live after disable_previews #3805), and empty-drop re-census stop rules.
  • Password hash/token lifetimes & Local trust (2 sections): Compressed phrasing while keeping first-boot configuredHashFunction() + synchronous SHA-256 password.validate default, per-mint lifetimes, _localPrincipal: true string marker, non-portability/getSuperUser minting, and per-call views with default role.id.
  • Named component children: Tightened bakery-lock and polling narration while keeping OS birth-identity formats (The constrained spawn hands back a recycled pid, or a zombie, as a component's process #2968), write-then-rename, cross-boot retirement, hidepid/permission-denied unknown handling and operator repair, legacy two-line coexistence residual, componentPreparationLock.ts ticket ordering, 1 s positive foreign-owner cache, release markers and dual-failure repair, shared claim protocol, 60 s cohort-progress wait bound, 30 s probe cap, intra-process worker limitation and deferred main-thread sweep, native PID handle residual, Windows exitCode/signalCode: null, NamedProcessError, and Windows-gated test notes.
  • Application lockdown, Scoped mirror, Resource attribute permissions & System permissions on roles: Tightened minor phrasing while keeping every lockdown mode/perf rule, UDS mirror readiness/reconciler/lockout check, restricted PATCH/PUT attribute semantics and gaps, and permission.system derivation unchanged in substance.

⚖️ Alternatives

  • Trim 1–5 KiB and leave design-docs-ceilings.json at 52,768 — check-design-docs.mjs --base HEAD^1 fails any edit to an over-ceiling file that leaves it above 60% of its ceiling (31,660 bytes).
  • Prune resources/DESIGN.md or resources/indexes/DESIGN.md in this PR — resources/DESIGN.md (3 bytes over ceiling) owes its own 40% cut in a separate change, and resources/indexes/DESIGN.md (22 bytes under ceiling) overlaps active index PRs.

✅ Verification

  • ⚠️ Look hardest: confirm no security invariant or residual risk was dropped in security/DESIGN.md (node build-tools/check-design-docs.mjs --stale reports zero dead symbol/path references and zero over-budget errors on security/DESIGN.md; all 15 #issue references and all named test pointers remain).
  • npm run check:design-docs and npm run check:design-docs -- --base origin/main pass for security/DESIGN.md and build-tools/design-docs-ceilings.json (only the pre-existing 3-byte overrun in resources/DESIGN.md from Clear a removed table TTL everywhere, reject invalid TTLs where they are declared, and scan catalog-loaded tables without a write #4250 remains on main).
  • NODE_OPTIONS=--conditions=typestrip npx mocha unitTests/build-tools/checkDesignDocs.test.mjs (59 passing), npm run lint, npm run check:unit-partition, and npx prettier --check security/DESIGN.md build-tools/design-docs-ceilings.json all pass.
  • End-to-end: not observable, because the change touches only internal design notes and ceiling metadata.

PR QA: skipped @ 1b40b71 — docs-only design-note trim and ceiling metadata update with no runtime behavior.

Docs: none needed (internal design notes only).

🤖 Generated by Google Gemini; posted via @kriszyp.

Release target: v5.4 — changed code is not on v5.3 1 absent file
Related PRs: #2906 overlaps (edits security/DESIGN.md), #2990 overlaps (edits security/DESIGN.md and design-docs-ceilings.json), #3485 overlaps (edits security/DESIGN.md and design-docs-ceilings.json), #4066 overlaps (edits security/DESIGN.md), #4069 overlaps (edits security/DESIGN.md), 1 other independent
Complexity: easy

Origin — the dispatch brief this PR was written from

Bring security/DESIGN.md back under its size ceiling so check:design-docs passes on main

npm run check:design-docs fails on harper main: security/DESIGN.md is 52,798 bytes, 30 over its ceiling of 52,768 (the ceiling only falls). Trim security/DESIGN.md so it passes with real headroom — remove or tighten narration, duplicated statements and anything the code already says; keep every invariant and rule. Do not raise the ceiling. Follow the precedent of "Bring config/DESIGN.md back under its 40 KiB budget (#4228)". Also report (do not change) the current headroom of resources/DESIGN.md and resources/indexes/DESIGN.md, which other tasks found within 90 and 22 bytes of their ceilings; if a prune of those is cheap and safe in the same spirit, include it, otherwise leave them. Run check:design-docs and lint. Open a PR.

Acceptance

check:design-docs passes on the branch; no invariant removed from security/DESIGN.md (list what was cut in the PR body); ceiling unchanged.

Dispatch: task harper-design-doc-ceiling-security · queued by kris-session · ran by gemini/gemini-4-carbon-high/low · worker kzyp-xps-1

Review-Coverage: authored=gemini; ran=cursor-composer,claude,cursor-grok; late=cursor-grok:adjudicated; adjudicated=domain; declined=muse; urgency=fast; rounds=3; full=1 @ 1b40b71

Review-Attention: read ~3m (decisions: wholesale-rewrite-vs-targeted-prune) @ 1b40b71

kriszyp and others added 3 commits November 11, 2026 11:02
#4110 left security/DESIGN.md at 52,798 bytes, 30 bytes over its
52,768-byte ceiling. Under --base, check-design-docs.mjs holds any edit to
an over-ceiling file to at most 60% of its ceiling (31,660 bytes), which
brings security/DESIGN.md within the 40,960-byte budget and retires its
entry from build-tools/design-docs-ceilings.json.

Trim prose narration, duplicated allowlist statements, and code-level
restatements across 16 sections down to 31,621 bytes while preserving
every invariant, symbol, issue reference, and enforcement test.

Dispatch-Task: harper-design-doc-ceiling-security
Co-Authored-By: Gemini <noreply@google.com>
Restore the purpose and Read-this-when header, the unchanged non-zero
userChangeNotificationEpoch() consumer guarantee, exact wording for the
three known _scopedToken by-name sites, preview system-table row
replication and empty-drop re-census stop rules, OIDC claims/provider
hooks, TLS transient-skew and backoff notes, named test-block pointers,
and named-process residual risks while staying at 31,574 bytes.

Dispatch-Task: harper-design-doc-ceiling-security
Co-Authored-By: Gemini <noreply@google.com>
State that operations: ['read_only'] does not block REST writes and that
table permissions still apply, keeping security/DESIGN.md at 31,612 bytes.

Dispatch-Task: harper-design-doc-ceiling-security
Co-Authored-By: Gemini <noreply@google.com>
@kriszyp kriszyp added this to the v5.4 milestone Nov 11, 2026
@kriszyp
kriszyp marked this pull request as ready for review November 11, 2026 22:17
@kriszyp
kriszyp merged commit 71c7ce6 into main Nov 11, 2026
92 of 111 checks passed
@kriszyp
kriszyp deleted the fix/security-design-doc-ceiling branch November 11, 2026 22:18
dawsontoth added a commit that referenced this pull request Nov 11, 2026
…fversion

Main's #4280 brought security/DESIGN.md under its budget and retired its
ceiling, so the conflict resolves to main's file plus this PR's session
sentences, and the PR no longer changes the ceilings file.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
kriszyp added a commit that referenced this pull request Nov 11, 2026
Upstream #4280 pruned security/DESIGN.md under its 40 KiB budget and retired its
ceiling, while #4216 left root DESIGN.md 2 bytes under its 68,166-byte ceiling.
Place the two #3485 compartment importHook invariants as subsections under the
indexed security/jsLoader.ts loader-gates note so root DESIGN.md and
build-tools/design-docs-ceilings.json stay untouched.

Dispatch-Task: pr-maint-8f11d60fac23bd5d253528880dc524d7
Co-Authored-By: Gemini <noreply@google.com>
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