Uh oh!
There was an error while loading. Please reload this page.
Add Request::withAttributes() — set several attributes in one instance - #7
Merged
Conversation
hakeemRash
requested review from
Alshatri and craftdevscommunity
as code ownersAugust 29, 2026 19:43
hakeemRash added a commit
to AlfaCode-Team/hkm-kernel
that referenced
this pull request
Aug 29, 2026
The pointer was d1b1366, which lived only in a local checkout on a detached HEAD. Nothing could resolve it: `git submodule update --init` fails for a clone and for CI, and `Kernel\Http\Request` never loads — while ResolveStage now calls withAttributes(), which exists in no pushed commit at all. Releasing against that pin would have shipped a kernel whose routing calls a method the published http package does not have. c4fe527 is the same change cherry-picked onto origin/main (AlfaCode-Team/http#7) and pushed, so the pin resolves.
Uh oh!
There was an error while loading. Please reload this page.
hakeemRash added a commit
to AlfaCode-Team/hkm-kernel
that referenced
this pull request
Aug 29, 2026
…OOT_CACHE work (#124) ## Why Four things in the kernel were documented as working and were not. Each is a case where a declaration read as a guarantee and compiled to nothing. ## The queue was not an authenticated channel `WorkerLoop` has always carried a signature check, but the kernel had no way to give it a key — `$signingSecret` defaulted to `''`, was never passed at construction, and no builder method existed. **In every deployment that has ever run, it was dead code and the worker executed whatever it was handed.** And the signature it would have checked covered `data` alone, leaving `jobClass` — the field deciding *which code runs* — unauthenticated. Capturing one legitimately signed envelope and swapping its class for any other `JobContract` was enough; no forgery required. `Kernel::withWorkerSecret()` makes the check reachable, and the material is now `jobId | jobClass | queue | maxAttempts | canonical(data)`. Off by default, and deliberately **not** falling back to `APP_KEY` — that would switch verification on everywhere at once and reject every job in flight. A payload that failed verification used to return `skipped()`, which `processWithPort` then **acked** — deleting the only evidence something is writing to your queue. It now dead-letters through the `ErrorPipeline`. ## BOOT_CACHE never hit `build()` computed `buildHash()` twice, before and after `resolveEssentialModules()` rewrites `essentials` from proj.json DOMAINS into provider CLASSES. Written under one hash, read under another — so every request recompiled all ten manifests *and* rewrote the stamp, **worse than leaving the flag off**. ``` BOOT_CACHE on, essentials=domain: 2865 us -> 39 us (per request, PHP-FPM) ``` `BootStampTest` tests the stamp in isolation and could not see this; `KernelBootCacheTest` builds twice through the real `Kernel::build()` and watches the manifest inode. ## Also - **No `pcntl` anywhere** — SIGTERM killed the worker mid-flight, including between `handle()` returning and `ack()`, so a job that had run its side effects came back and ran them again. - **`retry`/`timeout` in `module.json` compiled to nothing** — every job shared one hardcoded strategy. - **Request clones** — `ResolveStage` 10.02 -> 3.57 us; `SecurityGateway` 4.17 -> 0.87 us. - **`hkm run` ignored its documented `./` default** — an `args.len <= 2` guard fired before the resolver, which broke `hkm run --dev` specifically (`--dev` is stripped before parsing, so it arrived as exactly `["hkm","run"]`). ## Depends on **AlfaCode-Team/http#7** — `ResolveStage` calls `Request::withAttributes()`, which exists only there. The submodule is pinned to `c4fe527` from that PR's branch. **If #7 is squash-merged the SHA changes and this pin must be repointed before merging.** ## Verification 352 tests (from 312), PHPStan clean, launcher builds, and the dev server serves 200 on both routes. Benchmarks re-measured, not recalled. ## Risk Enabling job signing is a two-sided change: the `QueuePort` adapter must stamp `JobPayload::signatureFor()` at `push()` time. Until it does, every payload is rejected — correct, but roll it out producer-first. No migration is needed for the algorithm change, since nothing signed before.
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 freeto 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.
Every
with*()deep-clones all seven Symfony parameter bags, so a chain of them pays that price once per link.The kernel's
ResolveStageattachesroute_entry,route_paramsandtarget_service— one logical step that cost three full clones of a request nothing had read yet.withAttributes()does it in one.Measured on the kernel's routing step: 10.02 µs → 3.57 µs (64% less), and ~2.2 KB less garbage per request.
Identical in effect to chaining
withAttribute(); it just does not build the two intermediate requests that get thrown away. Immutability is unchanged — the original is untouched, and the kernel'sRequestTestasserts the batched result is byte-identical to the chain it replaces. An empty array returns$this, since there is nothing to copy.Required by hkm-kernel v1.6.0, which pins this commit as its
modules/httpsubmodule.🤖 Generated with Claude Code