Repository navigation
Conversation
… ordered emitter
addEvent awaited each event's SHA-256 digest before storing it, so overlapping calls on one step stored in digest-finish order: a slow digest put an event after later ones. master's runPrintJob makes such calls (printer-job.ts:196), so a print's signed bundle could list progress before started, and the IPP binding test flaked (#474, #456, #6307). Each step now keeps a chain: an event is hashed at its call, as before, and stored only after the step's earlier events are stored or have failed. The hashes still run concurrently, a refused event still rejects at once and takes no place, a failed hash rejects only its own call, and steps never wait on each other. Tests: refvertical's reproduction (#6343) and four gated cases in evidence-emitter-order.test.ts. The IPP binding test drops #571's ordered emitter (carried here) and gains a production-path case: runPrintJob with a plain emitter and a slow execution_started digest keeps the printer's order, in the signed bundle too.
…k 259) Three HIGH findings on #573 (astra pack 259). Each was reproduced at dce82e8, and on master's emitter, before this change: - finalizeBundle hashed the live events array, awaited the signer, then copied the array, so an add stored meanwhile appeared in bundle.events without being covered by bundleHash. It now waits for every add called before it, refuses a step that lost an accepted add, and hashes and returns ONE snapshot. An add called later is stored after the bundle and never enters it. - registerStep replaced a step while adds were pending, and those adds then resolved into a record nothing reads. It now refuses while adds are pending. A step whose adds have settled is still replaced, so a later run starts a fresh record. An add pending when its step is cleaned up now fails instead of storing. - Steps were keyed by the joined string job:step, so ("a:b", "c") and ("a", "b:c") shared one record and one chain. They are now two map levels. Tests: seven lifecycle cases in evidence-emitter-order.test.ts, six of which failed before the fix. Mutations: 15 of 15 killed. Kernel: 1140 of 1140.
…s (pack 261) Pack 261 found pack 259's HIGH 1 still open. The snapshot copied only the array, so its event objects were the stored ones that callers still hold: addEvent returns them and getEvents hands them out. A change made through such a reference while the bundle was signed reached the bundle. Reproduced at 239b944: the bundle's event was the caller's object, and after its hash was changed during signing, verifyBundleHash returned false. The snapshot is now a structuredClone of the stored events, so the bundle holds copies no caller can reach. A new test changes the caller's event (its hash and payload) while the signer is gated. The bundle keeps the original, and both its bundle hash and its event hash verify. Mutations: 16 of 16 killed (a shallow snapshot is the new mutant). Kernel: 1141 of 1141.
…resh full CI on a green master (steward #6465)
…o, copied at the call (pack 265 MEDIUM)
addEvent hashed and stored the adapter's own nested objects: it copied the
payload shallowly, so a change the adapter made after the call reached the
stored event, which then no longer matched its hash (fail closed: verification
refused it). Pack 265 kept that as a separate row (steward #6465), scoped as:
detach and validate the whole hash-covered input before hashing, source
included, and refuse shared memory and non-JSON values.
addEvent now takes its own deep copy (structuredClone) of exactly the four
fields the hash covers (type, timestamp, source, payload) at the call, hashes
and stores that copy, and hands callers copies from addEvent and getEvents. A
field outside those four is no longer stored, since the hash never covered it.
The copy alone does not make the hash faithful. Canonical JSON hashes a Date,
a Map, a Set, a RegExp or an Error as {}, a typed array as an object of its
indices, shared memory as its bytes of the moment (structuredClone keeps a
SharedArrayBuffer shared), a hole or an undefined element as null, and an
array without its named members, and JSON carries NaN and Infinity as null.
So the copy must be plain JSON data, checked before the event takes a place:
the values #359's canonicalize refuses, including D5's integers outside the
safe range, which the oracle and VCR refuse to hash.
Tests: the adapter changing its objects afterwards, callers changing returned
copies, bundle isolation, the plain JSON check (each refused kind, and plain
data accepted), and hashed fields only. Mutations 28 of 28.
LamaSu
had a problem deploying
to
trusted-checks
October 4, 2026 05:48 — with
GitHub Actions
Failure
…s comment (#578) Master's canonicalize writes an array hole, NaN and Infinity as text no JSON parser reads ([1,,3], NaN, Infinity), not as null; only an undefined element becomes null (probed). The oracle and VCR claim is narrowed to what they refuse: D5's integers outside the safe range. Comment only.
LamaSu
had a problem deploying
to
trusted-checks
October 4, 2026 05:50 — with
GitHub Actions
Failure
…ts tree passes the trusted secret scan (a plain merge)
LamaSu
had a problem deploying
to
trusted-checks
October 4, 2026 06:03 — with
GitHub Actions
Failure
… clean head tree and a fresh full CI (steward #6548; a plain merge)
…in merge; the tree is unchanged)
…y, with intrinsics captured at load, and refuses undefined (astra pack 273) Pack 273's HIGH and MEDIUM, both reproduced at 1538d6f, where the emitter is unchanged since 5bd1c1d: - HIGH: addEvent ran adapter code (a payload getter) before its copy. In astra's recipe, the getter swaps globalThis.structuredClone for identity, the adapter keeps a reference into the stored event, and a later change reached it: the stored reading became 99, and the hash no longer verified. With Object.getPrototypeOf replaced, a Date passed the plain-JSON check. - MEDIUM: {x: undefined} was stored with an own x, which the hash and JSON both drop; type, timestamp and source could be undefined. Fix: - addEvent first copies the four hashed fields (copyEventInput) through own property descriptors and node:util's trap-free proxy check, so no adapter code runs inside addEvent at all: no getter, setter or Proxy trap. - copyPlain refuses an accessor, a proxy, undefined anywhere (type, timestamp and source included), a symbol-keyed, non-enumerable or __proto__ member, a non-plain object (class instances too), a named array member, a hole, a non-finite number, D5's unsafe integers, and nesting past 64. - -0 is stored as 0, as JSON carries it. - The copy is built by defining properties, so no setter on a prototype runs. - Every intrinsic the boundary and the copies use is captured at load, structuredClone included, for addEvent's return, finalizeBundle's snapshot and getEvents. - The job and unit binding read and write own members of the copy only. Tests: - astra's recipe: refused, and the getter never runs; - an event getter and proxies: refused, with no trap run; - seven intrinsics replaced during the call change no refusal; - getEvents with structuredClone replaced still detaches; - setters and a `get` planted on Object.prototype: no setter runs, and nothing is lost; - a source scan for uncaptured intrinsic calls; - undefined members, nested and at the root; - refvertical's call-order test gives its events a source. Kernel 1154/1154. Mutations: 40 of 40, pack 265's 16 included.
…tra pack 273) The completion event carried summary: undefined whenever the sidecar sent no summary. Neither the event hash nor JSON keeps an undefined member, and the kernel's emitter now refuses one (pack 273's MEDIUM). The member is now set only when there is a summary. barrier-attestation's end-to-end run was the one test the stricter emitter failed; adapter-pylabrobot is 58/58.
LamaSu
had a problem deploying
to
trusted-checks
October 4, 2026 07:04 — with
GitHub Actions
Failure
…ray.prototype.push (astra pack 277) Pack 277's HIGH, reproduced at 6779123. The copy was sound, but the store still called the replaceable Array.prototype.push. A push replaced after load (astra's recipe: keep every event handed to it, then delegate) was handed the stored event, and could change it after it was hashed. In the reproduction the stored pages became 99 and verifyEventHash failed. The signed bundle's hash still verified, because hashBundle commits to the event-hash strings, while its event did not verify. - The element is now defined with the ObjectDefineProperty captured at load, through a null-prototype descriptor, so no push is called and nothing is handed out. - addEvent's comment no longer claims that no adapter code runs anywhere in it. It says what is covered: the copy, and the store. It also names what is not: the emitter's own Map lookups, the store chain's Promise then, and @pcc/spec's sha256, which can break ordering or fail a hash but cannot reach a stored copy. Tests: astra's reproduction, with the push replacement held across the store chain. Nothing is handed to it; the stored event, its hash, and the bundle (both its hash and its event) verify. The source scan also refuses any method call on a step's stored array. Kernel 1155/1155. Mutations: 41 of 41 killed (pack 265's 16, pack 273's 24, and the store through push).
LamaSu
had a problem deploying
to
trusted-checks
October 4, 2026 07:15 — with
GitHub Actions
Failure
…d by a closed allowlist (steward #6651, #6668) From addEvent through storage, getEvents, finalizeBundle and hashing, every call in evidence-emitter.ts now goes through a binding captured when the module loads, a function or class declared in the file, or a JS private member of the emitter; finalizeBundle also calls the onBundle callbacks. The order test parses the file with the TypeScript compiler and refuses anything else (member, computed, parameter and global callees, for-of, spread, instanceof, `in`, unpinned awaits), with a self-test on planted x.push(1), arr.map(f), this.foo(), map.get(k), promise.then(f), regex.test(s), obj.method() and the implicit forms. - Hashes: computed by the emitter, synchronously, with node:crypto's one-shot hash captured at load, byte for byte as spec's hashEvent and hashBundle. A captured crypto.subtle.digest is still forged by a replaced Promise.prototype.then (Node's async digest resolves through it), and createHash's wrapper by an accessor planted for its internal handle. - Chain: no then anywhere; every await is on a promise given its own pinned constructor; links fulfil with undefined. lost is gone: an accepted add can fail only by its step's cleanup, which finalizeBundle already refuses. - Map get/set/delete/size, WeakSet, Error, Date, String slice, Function bind, spec's canonicalize, ids.evidence/bundle, isFabricated, kernelPullCaptureIssue and Sentry.startSpan captured; RegExp replaced by a character check; registerStep copies the unit's two strings; state, signer and collaborators in JS private fields; storage methods bound when attached. - Tests: Map, Promise then/constructor/species, crypto.subtle.digest and node:crypto hash/createHash/kHandle/TextEncoder, RegExp, ids, Sentry and storage methods, and instance-property writes, each replaced during the calls; astra's push repro kept; hash equality with spec; the Object.prototype.then residual pinned. N123 and pack-259 tests no longer hold the digest (it cannot be held now); the handoff test holds adds at addEvent's boundary, and the scope test's echoing device echoes on the next event-loop turn.
…not only the allowlist - Map delete and size join get and set in the Map test: a second step is cleaned up while a size that says "empty" is in place, so an uncaptured size would drop the job's other step. - Error, Error[Symbol.hasInstance], WeakSet add/has, Date and toISOString, String.prototype.slice, console.warn (taken when the emitter is built) and Function.prototype.bind (used when a storage service is attached) replaced around the calls: the refusal keeps the emitter's message and prototype, the test signature and createdAt are real, the archive still runs. - checkTierRequirements with Array.prototype methods, its iterator, Set, Object.prototype.hasOwnProperty and spec's exported arrays changed answers as with them intact (non-camera events: spec's kernelPullCaptureIssue is a named residual).
…ts, so a live read changes the answer The mutation check found that reading DEFAULT_TIER_REQUIREMENTS live (instead of the copy taken at load) survived: the test emptied tier 1, which its events already meet. Tier 2, which they do not meet, now asks for nothing while the calls run, so a live read would answer met.
…s its step state by definition, checked default-deny (steward #6792) The emitter now passes the default-deny check that #519's admission passes (steward DECISIONS 01:30 and #6792, astra packs 289 and 291). builtin-reads-check.ts is a copy of @pcc/spec's, identical below its header. evidence-emitter-builtins.test.ts runs it over evidence-emitter.ts: - the trusted hasOwn and ObjectCreate are the emitter's own, captured at load; - the await wrapper is pinned(); - the self-test uses the same fixture lines as spec's. The emitter's changes: - Array and string elements are read through listAt and charAt. listAt is hasOwn over the hasOwnProperty captured at load; charAt is String.prototype.charAt captured at load. A hole or an index past the end never reaches a prototype. - A step record's pending, stored and detached are set by defineField (ObjectDefineProperty with a null-prototype descriptor), never by [[Set]], so a setter planted on a prototype never runs. - console is captured at load. Its warn is still bound when an emitter is built, the collaborator the order test replaces. - The input check's refusal message is read as its own data, not through Error.prototype. - The payload's commit pairs are records, read by property, instead of tuples read by index. Evidence: - The check reports nothing on evidence-emitter.ts. - kernel: 50 files, 1169 tests pass. - PyLabRobot adapter: 58/58. - gateway's emitter test: 21/21. - tsc is clean.
LamaSu
had a problem deploying
to
trusted-checks
October 4, 2026 10:50 — with
GitHub Actions
Failure
…und is no proof at the read (astra pack 293) This syncs the kernel copy of the default-deny check with @pcc/spec's after astra pack 293 (#519 @7f3067e2). The canonical string-loop allowance compared identifiers by spelling and allowed statements before the read, so it is removed. The copy is again identical below its header. The self-test's fixture lines match spec's: - the allowed string loop uses charAt; - canonicalLoop, shadowedRange, shadowedIndex and reassignedByCall are refused; - every misclassified line is listed in one assertion. The emitter already reads strings through charAt; the check still reports nothing there.
LamaSu
had a problem deploying
to
trusted-checks
October 4, 2026 10:55 — with
GitHub Actions
Failure
… replaceable after load (DECISIONS 04:06)
Under DECISIONS 04:06, the default-deny check covers the trusted path's computed transitive closure. The
kernel's evidence emitter reaches spec's canonicalize, the primordials helpers it uses, and ids.
- primordials.ts:
- listAt and charAt now sit beside hasOwn;
- includesValue, mapList, joinStrings, sortedStrings, deepFreeze and stringSet read elements only through
listAt, so a hole never continues to Array.prototype.
These shared-region lines are byte-identical to #519's, so the two branches merge cleanly.
- canonical.ts: #519's version verbatim. It reads a key only through listAt and a hasOwn guard, and an
element as the first statement of its guard.
- ids.ts: generateId uses Date.now, Math.random, Number.prototype.toString and String.prototype.substring
as captured at load.
Behavior on data is unchanged. spec: 77 files and 2422 tests pass; tsc is clean.
…y.prototype.find skipped it (astra pack 299) Astra pack 299, MEDIUM, reproduced at 6804552. A requirements list with a hole at 0 and a valid tier at 1 threw "Cannot read properties of undefined (reading 'tier')": listAt(requirements, r)! reached the hole. checkTierRequirements now skips a hole with hasOwn. The new test fails without the skip, with that TypeError. kernel: 50 files and 1170 tests pass; tsc is clean.
LamaSu
added a commit
that referenced
this pull request
Oct 4, 2026
…tive closure (DECISIONS 04:06) Steward DECISIONS 04:06: the check's scope is the trusted entry points' transitive in-repo call closure, computed from the TypeScript program, with no hand list. #519 adopts it before it merges; #578 uses the same check, kept identical below the header. - builtin-reads-check.ts: - trustedClosure computes every in-repo declaration the seed files reach. It follows ANY reference (a call, or a function passed, stored or captured as a value) through imports and re-exports, but not an import alone or a name used only in a type. - closureReads checks each reached declaration in place: what runs at load stays exempt. - A collaborator named with its reason is not entered, and the list is closed: an unused entry fails. - programOfFiles builds the multi-file self-test. - The test seeds profile-admission.ts. The closure reaches 165 declarations: primordials 56, evidence-level 45, plain-data 25, measurement-profile 20, subject-binding 13, evidence 2, primitives, is-fabricated, canonical and admission 1 each. It reports none. - The reach is asserted, so it is not vacuous. - A two-file self-test shows the closure follows a call and a stored function, skips an import named only in a type, and stops at a named collaborator. - primordials.ts: listAt and charAt move beside hasOwn, and every helper reads elements through listAt. These shared-region lines are byte-identical to #578's (75f1c81), so the branches merge cleanly. Mutations: - the closure following nothing: 2 tests fail; - a live JSON lookup planted in ownPromise, which only the closure reaches: reported. spec: 83 files and 2788 tests pass; tsc is clean.
…oad (astra pack 299) implementer-bravo The kernel's tier gate captures kernelPullCaptureIssue at load and asks it whether a camera event counts toward tier 2, but the function looked its intrinsics up when it ran: with RegExp.prototype.test replaced after load, a capture whose imageHash is "invalid" met tier 2 (reproduced at 6804552). The function and every helper it calls now go only through bindings captured when the module loads (spec's primordials plus a block of its own): - the image hash is checked code unit by code unit (no RegExp); - own data properties are copied onto null-prototype records, with keys in the dense array Reflect.ownKeys returns (no Map, no iterator protocol); every list is read by index, an element only where proven own; - a descriptor is data only when it owns `value` (no `in`), so a `value` written on Object.prototype never makes an accessor look like data; - the governed types are a copy taken at load (the export is mutable); - isFabricated is handed the null-prototype copies, so a `simulated` or `mock` written on Object.prototype is not read as the event's own. Same answers, reasons and order of checks for every input: the existing kernel-pull-capture suite passes unchanged. The default-deny builtin-reads check now reports nothing for the file (98 reports at 6804552). kernel-pull-capture-intrinsics.test.ts replaces 31 intrinsics and writes 5 values after load, over 53 valid and invalid events, and requires the untouched answers with no call of what was replaced.
… replaced after load (astra pack 299) implementer-bravo astra's reproduction at the emitter's tier gate, as a test: Tier 1 events plus an LO-SE-1 camera_snapshot whose imageHash is "invalid" give the same tier-2 answer (met false, the imageHash reason named) with RegExp.prototype.test replaced after load. At 6804552 that answer was { met: true, missing: [] }. Then each of 31 intrinsics replaced after load, and Object.prototype.value, Array.prototype[0] and the exported KERNEL_PULL_CAPTURE_TYPES written, one row each, over 24 camera events (valid captures and invalid ones, so a replacement that forces either answer is caught): every answer equals the untouched one and nothing replaced is called. Against spec built at 6804552, 27 of the 36 tests fail; all pass with the hardened function. The spec test's iterator symbol is annotated as the well-known one, so both new test files typecheck.
… simulated or mock at the camera gate implementer-bravo The mutation check showed two hardening points the kernel test could not see: `"value" in descriptor` reintroduced for the event's own fields (no fixture had an accessor at the event level), and isFabricated handed the caller's event instead of the null-prototype copies (no row wrote `simulated` or `mock` on Object.prototype). The spec test caught both. Add a stored camera event whose `payload` is an accessor (defined after stored(), whose spread would read it), and a describe that writes Object.prototype.simulated and .mock after load. That describe's Tier 1 events and valid capture carry null-prototype sources and payloads, because the emitter's own isFabricated call on the events it counts is a separate path that reads through prototypes; the refused captures keep ordinary objects, so an inherited `true` read as their own would change their reason.
…by name, so every call it makes is seen (astra pack 303) Under astra pack 303's rule, a call whose target is read back from a table of functions is a target the default-deny check cannot see. The rewritten kernelPullCaptureIssue still ran each field's check that way. The two check tables become: - ordered key lists (CAPTURE_KEYS, then INSPECTION_KEYS); - one fieldIssue(key, value, context) that holds each check in place, in a switch. An unknown key fails closed. The order of checks and every reason string are unchanged. A differential fuzz against 6804552's implementation found 2,000,000 of 2,000,000 answers identical (seeds 299 and 4207), and no getter ran inside either check.
… as own data, so a prototype's simulated or mock changes nothing Found by the implementer, then reproduced at the integrated head: - With Object.prototype.mock written after load, a valid Tier-2 set drops from met to not met. It fails closed, but on a prototype's value. - A getter planted on Object.prototype.simulated ran 4 times during one checkTierRequirements. checkTierRequirements now hands spec's isFabricated a null-prototype view of the event's OWN source.simulated and payload.mock, read through their descriptors, so no getter runs. An accessor or a Proxy on the way fails closed: the event is taken as fabricated and never counts. The test fails with the old IsFabricated(entry.event) call.
…h every call target seen or named (DECISIONS 04:06, astra packs 299 and 303) The kernel copy of the default-deny check now matches @pcc/spec's (#519 @b61262ae), identical below its header. - It computes the transitive in-repo closure (DECISIONS 04:06). - A call target it cannot see fails closed unless its exact call site is named with a reason (astra pack 303). - An instance field runs after load. - Collaborator keys are root-relative and exact. The test: - runs the same fixture lines, and the same two closure self-tests, as spec's; - seeds evidence-emitter.ts with @pcc/spec mapped to its source; - asserts the reach includes kernelPullCaptureIssue, fieldIssue, isFabricated, canonicalize, generateId, sortedStrings and listAt; - requires no reports. The CLOSED collaborator list, each with its reason: - the storage service's isReady and archiveBundle, which the closure reaches but does not enter; - the call sites of this.#warn, this.#signFn, this.#storageIsReady and this.#storageArchive; - Sentry's startSpan, captured at load; - the onBundle listener. Suites at this commit: spec 78 files and 2461 tests; kernel 51 files and 1212 tests; PyLabRobot 58/58; tsc clean for both packages.
LamaSu
had a problem deploying
to
trusted-checks
October 4, 2026 11:55 — with
GitHub Actions
Failure
… input as own data (astra pack 309)
checkTierRequirements read candidate.tier, event.type, requiredEventTypes,
minimumEvents and options.jobId through ordinary property access, so a write
on Object.prototype after load changed its answer: requirements [{}] met tier 2
with tier/requiredEventTypes/minimumEvents written there, and an
Object.prototype.type getter gave typeless events tier 1 (run 3 times).
Every field is now read through descriptors (ownField, ownElements,
ownGroups): no getter runs, nothing a prototype serves is read, and a Proxy,
an accessor or a field missing or of the wrong shape fails closed. The
caller's events stay unknown (kernelPullCaptureIssue and fabricated take
unknown); registerStep reads its unit the same way. isEvidenceInputError
answers a boolean and the storage service is held as unknown, so no caller
value takes a type it was never checked against.
Tests: both reproductions, a missing field not read from a prototype, and a
Proxy or accessor at each place in requirements, events, options and unit,
with zero traps and getters run. 6 of the 7 fail at 1a56cf2.
…n becomes typed only where its provenance is named (astra packs 307 and 309) The kernel copy of the default-deny check takes #519's a416bbc body (pack 307: an opaque callee's function operands must be seen code; module load-time statements join the closure) and adds the provenance rule: - an entry point's parameter whose type may be an object is the caller's object, used only as unknown: tested, compared, handed to an own-data reader (OWN_DATA_READERS, by the path it was captured from) or to in-repo code at an unknown parameter. Never read, aliased, held typed or destructured where it is received; - an unknown or any becomes an object type (as, a type predicate, an implicit any), and an assertion claims fields its operand lacks, only where CheckOptions.provenance names the place with where its own data comes from: a closed list, like the collaborators; - an unknown is handed to code the check does not walk only if that code is an own-data reader. The emitter names 4 conversions and 3 bind call sites (pack 307's rule). The fixture gains 5 allowed and 12 refused lines; each of 7 single-point mutations of the rule fails the test. Against 1a56cf2's emitter the rule reports every read astra's HIGH used.
…id on a final line terminator (astra pack 309 LOW) JavaScript's $ without the m flag matches only at the end of the input, so the former RegExp refused a trailing LF, CR, CRLF, U+2028 and U+2029, as the code-unit check does: the behavior is identical. The test pins that.
LamaSu
had a problem deploying
to
trusted-checks
October 4, 2026 12:50 — with
GitHub Actions
Failure
…ders include named in-repo captures (astra pack 309)
Closes a gap in the provenance rule: unknown narrowed by typeof to `object`
and then asserted to a readable shape (`(v as { tier: number }).tier`) was
not a conversion. An OPAQUE value (unknown, any, object, {}) taken as a
readable shape now is, and an opaque value handed to code the check does
not walk needs an own-data reader or a named call site.
Own-data readers also cover Object.keys, Reflect.apply of a reader
(ReflectApply(HasOwnProperty, o, [k])), the reject of an executor of the
Promise captured at load, and in-repo captures named in
CheckOptions.ownDataReaders (closed, like the collaborators).
The emitter's path names 4 more conversions (copyEventInput's two copies,
canonicalize's two record views), canonicalize's final String() call site,
and spec's nodeIsProxy as a reader. The fixture gains a named and an
unnamed reader, a narrowed-object assertion and an object handed to an
opaque callee. 10 single-point mutations of the rule each fail the test.
LamaSu
had a problem deploying
to
trusted-checks
October 4, 2026 13:00 — with
GitHub Actions
Failure
…ype minted only where a record is made (DECISIONS 05:05, astra pack 313) Astra pack 313 (DO-NOT-SHIP on aad2aee): the provenance rule laundered through types. A caller's object moved into a local unknown came back typed through an unconstrained generic (cast<T>), `as never as T`, a closure, a public method's this, or a collaborator's answer, and its fields were read with a dot. Reproduced at 5e002ce. A static type is no evidence (DECISIONS 05:05), so the check now asks where the receiver came from. The check (builtin-reads-check.ts): - a dot read (or destructuring) needs an OWNED receiver: its type carries the brand `[OWNED]` (a `declare const OWNED: unique symbol` in a primordials file), or it is a const bound to a fresh ObjectCreate(null) record or to a literal that defines the field, or a property descriptor read where hasOwn proves the field its own; - the brand is minted only on what the code makes (ObjectCreate(null), a literal defining every field, none optional, an array literal), or where CheckOptions.provenance names the snapshot; - assertions to a type parameter or to never are refused; - no owned type at the edge: an entry point's parameter, a callback opaque code calls, or what opaque code answers; - an object handed to code the check does not walk needs an own-data reader, a slot-read built-in, or a named call site; - writes by Object.defineProperty or a named writer land only on an owned snapshot, a fresh value, a private field or a promise, and an owned container is never widened where it is written. The 309 caller-value and named-conversion rules are subsumed and removed. The emitter: its step records, copied input, commit list, tier entries and ownProperty reads are owned literals or null-prototype records; copyPlain builds null-prototype records; every descriptor value read is proven own by hasOwn; the console's warn is read as own data; stored hashes are kept beside the events, so no stored event is read. spec's kernel-pull-capture owns its Fields and check context, and spec's primordials declares the brand. MEDIUM: setStorageService reads isReady and archiveBundle as the service's OWN data (ownField): an accessor, an inherited method, one Object.prototype serves, or a Proxy is refused, and no getter or trap runs. EvidenceStorageService now defines both on each instance. LOW: the options test now uses tier-2 camera evidence, where an unreadable jobId must fail the tier. Fixture: astra's forms each refused for their own reason; 14 single-point mutations of the rule each fail the test. spec 2462, kernel 1222, PLR 58, gateway 4803 (the same 5 jsdom files), tsc clean.
LamaSu
had a problem deploying
to
trusted-checks
October 4, 2026 13:36 — with
GitHub Actions
Failure
This branch had an error being deployed
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.
Pack 265's MEDIUM row (steward #6465), stacked on #573. Merge after #573: this branch carries #573's commits (head 95b48e8), and its own delta is the last commit.
Problem
addEventhashed and stored the adapter's own nested objects. It copied the payload only shallowly, so a change the adapter made after the call reached the stored event, which then no longer matched its own hash. Verification refused that event, so it failed closed. Pack 265 scoped the follow-up as: detach and validate the whole hash-covered input before hashing (source included), and refuse shared memory and non-JSON values.Fix (
packages/kernel/src/evidence-emitter.ts)A copy at the call.
addEventtakes its own deep copy (structuredClone) of exactly the four fields the hash covers: type, timestamp, source and payload. It hashes and stores that copy, and hands callers copies fromaddEventandgetEvents.Hashed fields only. A field outside those four is no longer stored, since the hash never covered it.
Plain JSON only. The copy must be plain JSON data, checked before the event takes a place. Canonical JSON has no faithful form for anything else:
{};structuredClonekeeps a SharedArrayBuffer shared);The check refuses the values fix(spec): canonicalize refuses values that have no JSON form #359's canonicalize refuses, including D5's integers outside the safe range, which the oracle and VCR refuse to hash.
Evidence
New tests (
evidence-emitter-order.test.ts). Four of the five fail at 95b48e8:The fifth, bundle isolation, passes there too: it guards fix(kernel): EvidenceEmitter stores a step's events in call order (N123) #573's snapshot in finalizeBundle.
Mutations: 28 of 28 killed (pack 265's set plus this round's).
Suites:
tsc --noEmitclean.Review: pack 273 (full round).
🤖 Generated with Claude Code