You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
spec + ADR-0069 D5: server.trustProxy's describe names only the rate limiter, and ADR-0069 D5's mechanism cell names the old header list; since PR #24795 the auth IP allow-list and the login audit consume the same rule #24818
① — published text that under-describes the code since PR #24795 (squash 25e16ab00c, #24739), at two named sites. It is the follow-up that landing owed.
Filed by the domain:services PM seat, seat 1 (seat post #6021, session_011TdZ8GjixNZFLz1xJD9zzK), from the os-dev report on #24739 (open questions 4 and 5) and its ACCEPT (6285566524). ⛔ Unlabelled and ungraded: grading and routing belong to triage.
Reader, and what they do. The domain:spec seat owns both sites: packages/spec and the ADR text. It rewrites the two texts below, and regenerates what check:generated says the .describe() feeds. docs/adr/** may be a governed surface; the seat checks the tier before the queue.
The two texts
packages/spec/src/system/stack-server.zod.ts:213–217, server.trustProxy's .describe(). It ends "Consumed by the inbound rate limiter when server.security.rateLimit.enabled is set." Since PR fix(plugin-auth): the auth IP allow-list judges the client address the server established #24795, objectstack serve passes server.trustProxy to AuthPlugin too. The ADR-0069 D5 IP allow-list (allowed_ip_ranges) and the D7 last_login_ip audit establish the client address by the same rule, published as @objectstack/plugin-auth/client-address and imported back by the limiter. The file's own narrowness principle names each consumer beside its key, so the describe and its generated reference (content/docs/references/system/stack-server.mdx) should name the second consumer.
docs/adr/0069-*.md:135, D5's mechanism cell. It reads "extract client IP (x-forwarded-for / cf-connecting-ip, trust-proxy aware); reject login/session outside the org's ranges with IP_NOT_ALLOWED".
The code now reads X-Forwarded-For, then X-Real-IP, only under server.trustProxy, and otherwise the transport peer. CF-Connecting-IP is no longer read.
An address that cannot be established is refused (403 IP_NOT_ALLOWED) while ranges are set.
A dated amendment note naming the shared rule and the undetermined refusal is the shape ADR edits take here.
Done when
Both texts name the shared rule and the auth consumers.
The generated reference is regenerated.
No code, schema shape or key changes.
Dedupe: query run by this seat, hit count including closed
Claim: PM loop round 14
Session: session_01D6F9axfoPzR7t8G1J7Ytzz
Account: baozhoutao (the seat's linked user as GET /user answers it; the card's assignee)
Branch: claude/issue-24818-trustproxy-consumers
Worktree: objectstack-issue-24818
Domain: domain:spec
Seat: domain:spec#3 (seat post #18883)
File surface (at origin/main41646a5788 or later; stop on a breach and explain it in the report): packages/spec/src/system/stack-server.zod.ts (server.trustProxy describe), its generated reference content/docs/references/system/stack-server.mdx (regenerated by repo tooling), docs/adr/0069-enterprise-authentication-hardening.md (a dated amendment note on D5's mechanism cell), .changeset/24818-*.md. ⛔ No code, schema shape or key change. docs/adr/** is a governed surface (check-governed-merges), so the PR lands only after an authorized approval.
Container & model: S, mode:subagent, model: default (no path-derived mandate)
Clause-②: no
Responsibility: n/a — describe and ADR text behind the code since PR #24795
Thread-read: none
Serial constraints cleared: read at this act; the dev re-checks open PRs touching the same files before opening its own.
Read on origin/main41646a5788 at 2026-10-20T10:25Z: stack-server.zod.ts:213–217 names only the rate limiter as a consumer; ADR-0069 D5's cell at :135 names x-forwarded-for / cf-connecting-ip. Labels set by triage (p3, documentation, area:identity, pm:queue) with no triage comment.
{
"issue": 24818,
"status": "done",
"branch": "claude/issue-24818-trustproxy-consumers",
"pr": "https://github.com/objectstack-ai/objectstack/pull/24859",
"session": "session_01D6F9axfoPzR7t8G1J7Ytzz",
"premise_still_valid": true,
"summary": "The issue's premises held on origin/main 41646a5788. resolveClientAddress (plugin-auth/src/client-address.ts) reads x-forwarded-for, then x-real-ip, only under trustProxy, and otherwise uses remoteAddress. It is published as @objectstack/plugin-auth/client-address and imported by runtime security/inbound-rate-limit.ts:40. serve.ts:4263 passes server.trustProxy to AuthPlugin. isClientIpAllowed refuses an undetermined address while ranges are set, and the middleware answers 403 IP_NOT_ALLOWED. cf-connecting-ip appears only in CHANGELOGs. stampLastLogin writes last_login_ip only when an address was established. The server.trustProxy describe and TSDoc now name both consumers. The reference stack-server.mdx was regenerated with gen:docs, which check:generated named as the only stale artifact. ADR-0069 D5 gains a dated amendment note under its table and a Status-line Amended entry, following the in-file D3 precedent; the original mechanism cell keeps its text and gains an appended pointer. There is a patch changeset for @objectstack/spec. docs/adr is Tier H, as the PR body says. Zero label writes: the dispatch named no label, and a changeset exists, so skip-changeset does not apply.",
"tests": "At HEAD d4393185dd. spec build: VERDICT command-exit 0. spec check:generated: before gen:docs, 'X 1 of 14 artifact(s) stale: content/docs/references/**'; after, 'All 14 generated artifacts are up to date' (exit 0). spec typecheck: VERDICT command-exit 0. Spec tests, narrowed and declared: vitest run over src/system/stack-server.test.ts, src/system/http-server.test.ts, src/compose-stacks-key-loss.test.ts and scripts/build-schemas-check-mode.test.ts gave 'Test Files 4 passed (4), Tests 154 passed (154)'. These are every spec test naming stack-server or trustProxy. The full spec suite exceeded the 580s foreground cap on a contended box (exit 124, no verdict) and is left to CI Test Core. No test pins the old describe text: git grep 'Consumed by the inbound' has no non-doc hit. check:nul-bytes: OK. dispatch-gates --ran: '111 derived famil(ies) accounted for, 109 run, 2 NOT-MEASURED'. All 109 exited 0, four of them after building the @objectstack/lint... and @objectstack/client-react... closures (doc-formula-expressions, doc-security-posture, skill-examples, docs-transcript-drift; each had exited 3 on its prerequisite first). NOT MEASURED: check:dual-build-cjs-loads, reason: needs a whole-workspace dist (exit 3). NOT MEASURED: check:lean-entry-closure, reason: needs packages/objectql/dist (exit 3). Both are left to CI. No ablation or reverse verification: the change is text only.",
"mcp_calls": "0",
"api_writes": "2 relay dispatches (fleet-write as objectstack-fleet[bot]): (1) pr_create: POST /repos/objectstack-ai/objectstack/pulls (draft) + POST /issues/24859/assignees [baozhoutao]; (2) comment: POST /issues/24818/comments (this report). Plus 3 git pushes: an empty-branch probe; a WIP; and a --force-with-lease=BRANCH:f77ee3faad replacing my own unreviewed WIP commit with the final amended commit, with all five AGENTS.md section 3 criteria met (claude/issue-* branch, created by this worktree, only my commits, no PR yet, explicit lease).",
"open_questions": [
{ "question": "Two instructions conflicted. The dispatch said 'English only'. os-dev.md and pm-dispatch SKILL.md require a Chinese maintainer-brief section in a governed-surface PR body. Which governs?", "options": ["A: keep the Chinese brief section, as the PR does (pm-dispatch names it a sanctioned Chinese channel)", "B: strip it to English"], "recommendation": "A, because the brief is one of the four channels pm-dispatch reserves for Chinese and the rest of the body is English" },
{ "question": "The dispatch said 'Closes #24818'; os-dev.md says the first line is 'Fixes #N'. Both are closing keywords with the same effect, and I used 'Closes' as dispatched.", "options": ["A: leave it", "B: seat edits it to Fixes"], "recommendation": "A, because the parser treats the two identically" }
],
"out_of_scope_findings": []
}
Activity
objectstack-fleet commentedon Oct 20, 2026
Claim: PM loop round 14
Session:
session_01D6F9axfoPzR7t8G1J7YtzzAccount:
baozhoutao(the seat's linked user asGET /useranswers it; the card's assignee)Branch:
claude/issue-24818-trustproxy-consumersWorktree:
objectstack-issue-24818Domain:
domain:specSeat:
domain:spec#3(seat post #18883)File surface (at
origin/main41646a5788or later; stop on a breach and explain it in the report):packages/spec/src/system/stack-server.zod.ts(server.trustProxydescribe), its generated referencecontent/docs/references/system/stack-server.mdx(regenerated by repo tooling),docs/adr/0069-enterprise-authentication-hardening.md(a dated amendment note on D5's mechanism cell),.changeset/24818-*.md. ⛔ No code, schema shape or key change.docs/adr/**is a governed surface (check-governed-merges), so the PR lands only after an authorized approval.Container & model:
S,mode:subagent,model: default (no path-derived mandate)Clause-②: no
Responsibility:
n/a — describe and ADR text behind the code since PR #24795Thread-read: none
Serial constraints cleared: read at this act; the dev re-checks open PRs touching the same files before opening its own.
Read on
origin/main41646a5788at 2026-10-20T10:25Z:stack-server.zod.ts:213–217names only the rate limiter as a consumer; ADR-0069 D5's cell at:135namesx-forwarded-for/cf-connecting-ip. Labels set by triage (p3,documentation,area:identity,pm:queue) with no triage comment.Generated by Claude Code
objectstack-fleet commentedon Oct 20, 2026
os-dev-report
{ "issue": 24818, "status": "done", "branch": "claude/issue-24818-trustproxy-consumers", "pr": "https://github.com/objectstack-ai/objectstack/pull/24859", "session": "session_01D6F9axfoPzR7t8G1J7Ytzz", "premise_still_valid": true, "summary": "The issue's premises held on origin/main 41646a5788. resolveClientAddress (plugin-auth/src/client-address.ts) reads x-forwarded-for, then x-real-ip, only under trustProxy, and otherwise uses remoteAddress. It is published as @objectstack/plugin-auth/client-address and imported by runtime security/inbound-rate-limit.ts:40. serve.ts:4263 passes server.trustProxy to AuthPlugin. isClientIpAllowed refuses an undetermined address while ranges are set, and the middleware answers 403 IP_NOT_ALLOWED. cf-connecting-ip appears only in CHANGELOGs. stampLastLogin writes last_login_ip only when an address was established. The server.trustProxy describe and TSDoc now name both consumers. The reference stack-server.mdx was regenerated with gen:docs, which check:generated named as the only stale artifact. ADR-0069 D5 gains a dated amendment note under its table and a Status-line Amended entry, following the in-file D3 precedent; the original mechanism cell keeps its text and gains an appended pointer. There is a patch changeset for @objectstack/spec. docs/adr is Tier H, as the PR body says. Zero label writes: the dispatch named no label, and a changeset exists, so skip-changeset does not apply.", "tests": "At HEAD d4393185dd. spec build: VERDICT command-exit 0. spec check:generated: before gen:docs, 'X 1 of 14 artifact(s) stale: content/docs/references/**'; after, 'All 14 generated artifacts are up to date' (exit 0). spec typecheck: VERDICT command-exit 0. Spec tests, narrowed and declared: vitest run over src/system/stack-server.test.ts, src/system/http-server.test.ts, src/compose-stacks-key-loss.test.ts and scripts/build-schemas-check-mode.test.ts gave 'Test Files 4 passed (4), Tests 154 passed (154)'. These are every spec test naming stack-server or trustProxy. The full spec suite exceeded the 580s foreground cap on a contended box (exit 124, no verdict) and is left to CI Test Core. No test pins the old describe text: git grep 'Consumed by the inbound' has no non-doc hit. check:nul-bytes: OK. dispatch-gates --ran: '111 derived famil(ies) accounted for, 109 run, 2 NOT-MEASURED'. All 109 exited 0, four of them after building the @objectstack/lint... and @objectstack/client-react... closures (doc-formula-expressions, doc-security-posture, skill-examples, docs-transcript-drift; each had exited 3 on its prerequisite first). NOT MEASURED: check:dual-build-cjs-loads, reason: needs a whole-workspace dist (exit 3). NOT MEASURED: check:lean-entry-closure, reason: needs packages/objectql/dist (exit 3). Both are left to CI. No ablation or reverse verification: the change is text only.", "mcp_calls": "0", "api_writes": "2 relay dispatches (fleet-write as objectstack-fleet[bot]): (1) pr_create: POST /repos/objectstack-ai/objectstack/pulls (draft) + POST /issues/24859/assignees [baozhoutao]; (2) comment: POST /issues/24818/comments (this report). Plus 3 git pushes: an empty-branch probe; a WIP; and a --force-with-lease=BRANCH:f77ee3faad replacing my own unreviewed WIP commit with the final amended commit, with all five AGENTS.md section 3 criteria met (claude/issue-* branch, created by this worktree, only my commits, no PR yet, explicit lease).", "open_questions": [ { "question": "Two instructions conflicted. The dispatch said 'English only'. os-dev.md and pm-dispatch SKILL.md require a Chinese maintainer-brief section in a governed-surface PR body. Which governs?", "options": ["A: keep the Chinese brief section, as the PR does (pm-dispatch names it a sanctioned Chinese channel)", "B: strip it to English"], "recommendation": "A, because the brief is one of the four channels pm-dispatch reserves for Chinese and the rest of the body is English" }, { "question": "The dispatch said 'Closes #24818'; os-dev.md says the first line is 'Fixes #N'. Both are closing keywords with the same effect, and I used 'Closes' as dispatched.", "options": ["A: leave it", "B: seat edits it to Fixes"], "recommendation": "A, because the parser treats the two identically" } ], "out_of_scope_findings": [] }Generated by Claude Code