Repository navigation
Add integration anchors for sealed re-declaration and local-principal isolation - #3808
Merged
kriszyp merged 5 commits intoOct 30, 2026
Merged
Conversation
… isolation Promotes two security-lane regression specs. sealed-redeclare-tracked-update (#3594): a sealed table refuses an undeclared own property assigned on a tracked Table.update() instance, across a two-worker re-declaration. Rejected arms now assert detail[0].code === 'unknown_property' and an unchanged updatedAt. local-principal-isolation (#3755): nothing from a non-loopback source becomes the `local` principal. The listener address is HARPER_TEST_NON_LOOPBACK_ADDRESS or the first external IPv4 interface (suite skipped when there is none), ports are allocated per run, the scoped-token mint must succeed, the dead `name === 'local'` clause is gone, and a new check covers a principal named `local` without the _localPrincipal marker. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Dispatch-Task: harper-promote-sealed-update-and-local-principal-anchors
Bound network waits, fail the sealed setup when a worker does not converge, keep tokens and cookies out of the logs, use a plain role for the look-alike users so a local-principal substitution cannot hide behind super_user, and drop the dead MQTT poll. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Dispatch-Task: harper-promote-sealed-update-and-local-principal-anchors
The gate budget is 60 s; the HTTP idle timeout and the 30 s default maxTransactionOpenTime sat inside it. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Dispatch-Task: harper-promote-sealed-update-and-local-principal-anchors
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Dispatch-Task: harper-promote-sealed-update-and-local-principal-anchors
Contributor
There was a problem hiding this comment.
Code Review
This pull request introduces comprehensive integration tests covering sealed table re-declarations across multiple workers and local principal isolation security mechanisms. The review feedback identifies two potential sources of test flakiness: a regex assertion in the sealed table tests that could falsely fail if a worker's thread ID matches an excluded value, and asynchronous session writes in the security tests that should be polled with a timeout rather than asserted immediately.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Dispatch-Task: harper-promote-sealed-update-and-local-principal-anchors
kriszyp
marked this pull request as ready for review
October 30, 2026 16:47
kriszyp
deleted the
test/promote-sealed-update-and-local-principal-anchors
branch
October 30, 2026 16:47
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
⊙ Problem
Two security regressions fixed on main — #3594 (sealed tables with tracked updates across a table re-declaration) and #3755 (the
localprincipal) — had only single-process or domain-socket coverage. Nothing checked them across two HTTP workers, or from a real non-loopback source address.🤔 Is a test-only PR the right fix?
As specified, yes. Both fixes are on main; what is missing is a test that fails when they regress.
💡 Solution
Two integration suites pass on RocksDB and LMDB and fail on the pre-fix base.
database/sealed-redeclare-tracked-update: a sealed table rejects an undeclared own property assigned on aTable.update()instance next to a declared edit, with 2 HTTP workers. Rejected arms assertdetail[0].code === 'unknown_property'and an unchangedupdatedAt.security/local-principal-isolation: nothing from a non-loopback address becomes thelocalprincipal (headers, bodyhdb_user, pre-auth header, replayed cookies, MQTT, minted tokens, scoped token, reserved name).🤔 Which non-loopback address does the security suite use?
HARPER_TEST_NON_LOOPBACK_ADDRESS, else the first external IPv4 interface of the host. With neither, the suite skips with that reason. A CI runner with no external IPv4 would skip silently; the other choice is a dedicated network namespace.🔧 Changes
integrationTests/database/sealed-redeclare-tracked-update.test.tsand its fixture (resources.js,config.yaml): seven held handles, four fresh handles, two REST patches, one re-declaration in worker B.integrationTests/security/local-principal-isolation.test.tsand its fixture (resources.js,config.yaml,schema.graphql): eight arms plus a direct check that a principal namedlocalwithout the_localPrincipalmarker gets no local role. The address choice and skip and per-run ports replace the hard-coded docker0 address; the scoped-token mint must return 200. Look hardest at the address choice.✅ Verification
83d515f2d); the security suite fails 4 cases on the parent of Run local-trust requests as a fixedlocalprincipal instead of re-reading a stored super user per request #3755's merge commit.isLocalPrincipalto check the name only turns the new direct check and arm 8 red.HARPER_TEST_NON_LOOPBACK_ADDRESS.Docs: none; test-only.
🤖 Generated by Anthropic Claude (Sonnet 5.5, dispatch dev agent); posted via @kriszyp.
Release target: v5.4 — test-only; the fixes under test are not on v5.3
Related PRs: #3594 overlaps, #3653 independent, #3803 independent, #3610 independent
Complexity: medium
Late Grok findings
12 surviving (highest minor) — Grok reviewed 5b7ab01
integrationTests/database/sealed-redeclare-tracked-update/resources.js:58— a held handle can be aborted by the open-transaction limit inside the time budgets the test allows itself. Arms then fail with an "open too long" 422 instead ofunknown_property, and the setup test still passesintegrationTests/database/sealed-redeclare-tracked-update.test.ts:163—request()has no timeout, andonThread/waitForcheck their deadlines only between awaits. A stalled exchange hangs thebeforehook with no attribution instead of failing itintegrationTests/security/local-principal-isolation.test.ts:614—note()(console.log, line 51) writes credential values to CI stdoutintegrationTests/database/sealed-redeclare-tracked-update.test.ts:378— the\b7\b|\b99\bscan runs over successful response bodies, which containthreadId. A worker whosethreadIdis 7 or 99 fails A4, A4p or B4 although no attempted value was storedintegrationTests/security/local-principal-isolation.test.ts:752— arm 6 can pass vacuously, and its look-alike users are created as super usersintegrationTests/security/local-principal-isolation.test.ts:71—freePortscloses the probe servers without awaiting the close, andopenMqtt(lines 228-253) has no connect or upgrade timeoutintegrationTests/security/local-principal-isolation.test.ts:546— after a refused CONNACK,mqttAttemptreturns before publishing (line 289). TheitemStatus(remote.itemId)404 check (also at line 853) therefore cannot fail once line 544 passesintegrationTests/database/sealed-redeclare-tracked-update.test.ts:419—body.threadId ?? threadAfalls back tothreadAon 4xx bodies, so the assertion is always true on rejected armsintegrationTests/database/sealed-redeclare-tracked-update.test.ts:331— a convergence failure is caught, the gate still opens, and the arms run against an unconverged schemaintegrationTests/database/sealed-redeclare-tracked-update.test.ts:261— added comments narrate the next line or act as section bannersintegrationTests/security/local-principal-isolation/resources.js:3— the fixture uses the loader-injectedResourceanddatabasesglobals, while the sibling fixture in this PR imports fromharperintegrationTests/database/sealed-redeclare-tracked-update.test.ts:17— the suite title includes[engine=…], but the run note gives noHARPER_STORAGE_ENGINE=lmdbinvocationNot standing: 3 merged. Grok ran 19m (19m from launch to report); the fold adjudication (
cursor-grok@5b7ab01b1c30-97417a8d, claude) took 2m.Review-Coverage: authored=claude; ran=cursor-composer,gemini,codex,cursor-grok; late=cursor-grok:adjudicated; adjudicated=domain,domain(codex); declined=muse; rounds=4; full=2 @ 052b543
Review-Attention: read ~4m (decisions: do-less-alternative, platform-scope, retired-field-semantics) @ 052b543