From 158849031bba78025d0ec16c8361628211fbc4ed Mon Sep 17 00:00:00 2001 From: Rickylabs Date: Sat, 8 Aug 2026 18:50:28 +0200 Subject: [PATCH 01/12] docs(rfc): activate sdk client contribution run --- .../codex-thread-ids.md | 16 +++ .../context-pack.md | 73 +++++++++++ .../drift.md | 33 +++++ .../implement.md | 73 +++++++++++ .../plan.md | 118 ++++++++++++++++++ .../research.md | 38 ++++++ .../supervisor.md | 35 ++++++ .../worklog.md | 96 ++++++++++++++ 8 files changed, 482 insertions(+) create mode 100644 .llm/runs/docs-rfc-sdk-client-contribution--rfc/codex-thread-ids.md create mode 100644 .llm/runs/docs-rfc-sdk-client-contribution--rfc/context-pack.md create mode 100644 .llm/runs/docs-rfc-sdk-client-contribution--rfc/drift.md create mode 100644 .llm/runs/docs-rfc-sdk-client-contribution--rfc/implement.md create mode 100644 .llm/runs/docs-rfc-sdk-client-contribution--rfc/plan.md create mode 100644 .llm/runs/docs-rfc-sdk-client-contribution--rfc/research.md create mode 100644 .llm/runs/docs-rfc-sdk-client-contribution--rfc/supervisor.md create mode 100644 .llm/runs/docs-rfc-sdk-client-contribution--rfc/worklog.md diff --git a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/codex-thread-ids.md b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/codex-thread-ids.md new file mode 100644 index 0000000000..3a16f7ee6d --- /dev/null +++ b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/codex-thread-ids.md @@ -0,0 +1,16 @@ +# rfc-sdk-client — Codex implementation thread +- **Thread / session id:** `019fe242-2bd9-7ff3-8044-bd9d09585397` +- **Rollout:** `/home/codex/.codex/sessions/2026/08/08/rollout-2026-08-08T18-43-35-019fe242-2bd9-7ff3-8044-bd9d09585397.jsonl` +- **Worktree:** `/home/codex/repos/ns-rfc-sdk-client` +- **Branch:** `docs/rfc-sdk-client-contribution` @ `fac9e3390` (NO upstream by design). +- **Push rule:** explicit refspec only — `git push origin HEAD:refs/heads/docs/rfc-sdk-client-contribution`. +- **Requested route:** provider=openai · model=gpt-5.6-sol · effort=xhigh +- **Observed route:** provider=openai · model=gpt-5.6-sol · effort=xhigh +- **Route verdict:** matched +- **Runtime:** approval=never · sandbox=dangerFullAccess +- **Brief (staged):** `/home/codex/rfc-sdk-client-brief.md` +## Steering (same thread — never a second send-message-v2 at this worktree) +```bash +codex exec resume 019fe242-2bd9-7ff3-8044-bd9d09585397 -- "" +``` +_Written by `.llm/tools/agentic/codex/launch-codex-slice.ts`._ \ No newline at end of file diff --git a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/context-pack.md b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/context-pack.md new file mode 100644 index 0000000000..0b1718f0f6 --- /dev/null +++ b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/context-pack.md @@ -0,0 +1,73 @@ +# Context Pack: typed SDK client contribution RFC + +## Run Metadata + +| Field | Value | +| --- | --- | +| Run ID | `docs-rfc-sdk-client-contribution--rfc` | +| Branch | `docs/rfc-sdk-client-contribution` | +| Current phase | `research` | +| Archetype | `2 + 4 + 5 + 6` described; docs-only PR | +| Scope overlays | `SCOPE-docs` | + +## Current State + +The harness run is activated on the exact requested base. Required skills, RFC process, harness +authorities, doctrine, selected archetypes, relevant debt, and the complete carried-in RFC-A design +pack have been read. No product code or RFC draft has yet been authored. + +## Completed + +- Exact base/worktree/session/GitHub-auth verification. +- Harness/doctrine/RFC authority read and archetype/overlay selection. +- Bootstrap artifact creation while preserving the launch-generated `implement.md` and + `codex-thread-ids.md`. + +## In Progress + +- Initial bootstrap commit, explicit-refspec push, and draft PR opening. + +## Next Steps + +1. Open the draft PR with the required labels and `status:research`. +2. Re-baseline live issues/PRs and current public/export/test surfaces through `deno doc` and + focused source reads. +3. Run type probes and upstream primary-source research; lock design and author the RFC. + +## Key Decisions + +| Decision | Source | Notes | +| --- | --- | --- | +| Keep `0000` and Draft state. | `rfcs/README.md` | Maintainer assigns number at acceptance. | +| Stop at external review handoff. | Owner brief | Generator must not trigger evaluator sessions. | +| No framework source in this PR. | Owner brief | Type probes live only under ignored/non-product `.llm/tmp/`. | + +## Files Changed + +| Path | Status | Notes | +| --- | --- | --- | +| `.llm/runs/docs-rfc-sdk-client-contribution--rfc/` | new | Mandatory run artifacts plus existing launch records | + +## Gates + +| Gate family | Current status | Evidence | +| --- | --- | --- | +| Static | pending | after RFC draft | +| Fitness | planning | union selected from Archetypes 2/4/5/6; docs PR gates to be locked | +| Runtime | N/A for RFC PR | no runtime implementation | +| Consumer | research pending | API/type probes and current consumers | + +## Open Questions + +- All design forks in the task brief remain open until the re-baseline is complete. + +## Drift and Debt + +- Drift: runtime-controller identity miss recorded in `drift.md`; launch artifact remains the + concrete session proof. +- Debt: no new debt; relevant existing entries are summarized in `plan.md`. + +## Commits + +- See the draft PR's commit list + per-slice PR comments (V3 retired `commits.md`). + diff --git a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/drift.md b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/drift.md new file mode 100644 index 0000000000..c998455c3b --- /dev/null +++ b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/drift.md @@ -0,0 +1,33 @@ +# Drift Log: typed SDK client contribution RFC + +Drift is append-only. Record facts that diverge from the plan, RFC, doctrine, or current-state +documentation. + +## 2026-08-08 — Active desktop thread is not registered in runtime-controller state + +- **What:** `deno task agentic:runtime status --worktree /home/codex/repos/ns-rfc-sdk-client` + returned `MISSING_IDENTITY`, while the launch-generated run artifact identifies this live thread, + rollout, worktree, requested/observed route, and full-access policy. +- **Source:** `.llm/tools/agentic/runtime`; `codex-thread-ids.md`; current session context. +- **Expected:** A daemon-attached session would also be discoverable by the desired-state runtime + controller. +- **Actual:** The thread is mobile/desktop launch-attached but not present in controller session + state (`sessions: 0`). +- **Severity:** minor. +- **Action:** accept for this docs-only generator run. Do not repair or relaunch: the owner forbids + a rival session and the concrete launch identity is already recorded. +- **Evidence:** runtime command exit 3 with `MISSING_IDENTITY`; thread + `019fe242-2bd9-7ff3-8044-bd9d09585397`; rollout path in `codex-thread-ids.md`. + +## 2026-08-08 — Owner-directed review route differs from default formal evaluator lane + +- **What:** The brief reserves cross-RFC review for the existing Claude Fable 5 session and a final + Qwen adversarial pass, and forbids this generator from triggering PLAN-EVAL/IMPL-EVAL. +- **Source:** owner brief. +- **Expected:** Default local formal PLAN-EVAL uses the open-model route in `lane-policy.md`. +- **Actual:** Review orchestration and route identity are explicitly delegated to the root + orchestrator. +- **Severity:** significant process override, owner-authorized. +- **Action:** stop at `status:plan-eval`, provide exact reviewer instructions, and let the root + orchestrator record observed evaluator identities/verdicts. +- **Evidence:** `implement.md` § Required output 5; `supervisor.md` routes table. diff --git a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/implement.md b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/implement.md new file mode 100644 index 0000000000..96cb4868bd --- /dev/null +++ b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/implement.md @@ -0,0 +1,73 @@ +use harness + +# RFC-A implementation brief — typed SDK client contribution seam + +You are the sole generator for a production-grade NetScript RFC. Work autonomously in +`/home/codex/repos/ns-rfc-sdk-client` on branch `docs/rfc-sdk-client-contribution`, based on +`origin/main` at `fac9e339042c`. You are Codex GPT-5.6 Sol at xhigh reasoning, full-access/bypass +permissions. Do not create a rival session or delegate the core RFC authorship. + +## SKILL + +- `netscript-harness` — activate the full harness and RFC/docs design run; maintain every mandatory run artifact. +- `netscript-doctrine` — evaluate the proposed public SDK/plugin extension seam against axioms, extension-axis law, layering, anti-patterns, and debt. +- `netscript-pr` — open and maintain a draft RFC PR to `main`, with correct labels, phase comments, and no premature merge/closure. +- `netscript-tools` — use repo-native validation and compact evidence tooling. +- `netscript-deno-toolchain` — inspect current public APIs through `deno doc` and native dependency/package tools rather than assumptions. +- `jsr-audit` — assess export and publish-surface consequences of the proposed SDK seam. +- `rtk` — reduce read-heavy command output without changing semantics. +- `codex-wsl-remote` — preserve the daemon-attached, mobile-visible session and explicit-refspec push safety. + +## Objective + +Turn Claude Fable 5's RFC-A proposal into the actual lightweight RFC required by `rfcs/README.md`. +The input is a starting proposal, not ground truth: + +- proposal: `/home/codex/repos/netscript-fable5-remediation-plan/.llm/runs/plan-fable5-remediation-roadmap--seed/fable-5-remediation-plan/rfcs/RFC-A-sdk-client-composition.md` +- tracking issue: `#1348` +- related filed issues: `#1349`–`#1353`, plus live dependencies named by the proposal +- source roadmap PR: `#1347` + +Re-baseline every claim against current `origin/main`, current docs, doctrine, exports, tests, and +live issue/PR state. Deeply analyze the type system and prove the proposed extension axis is both +general and minimal. Auth/headers are the first dogfood consumer, not a hardcoded special case; +prove a second non-auth contribution. Resolve or explicitly frame every design fork: contribution +ordering, conflict/duplicate policy, async request context, redaction, transport ownership, +generated-client ergonomics, oRPC alignment, plugin discovery, compatibility, failure modes, +inference budgets, and migration. Do not invent a parallel framework when an existing seam can be +unhidden or composed. + +## Required output + +1. Activate a new harness run at `.llm/runs/docs-rfc-sdk-client-contribution--rfc/` with + `supervisor.md`, `research.md`, `plan.md`, `worklog.md` (including `## Design`), + `context-pack.md`, `drift.md`, and a final handoff. Select `SCOPE-docs` plus every underlying + package/plugin archetype the RFC describes; read the RFC process, doctrine files, gate matrix, + plan gate, and evaluator protocol completely. +2. Produce `rfcs/0000-sdk-client-contributions.md` from `rfcs/0000-template.md`, keeping `0000` + until maintainer acceptance. The RFC must be decision-complete enough to implement: motivation, + terminology, exact public/type-level surface with realistic examples, invariants, composition + and ordering law, security/privacy and redaction, compatibility/migration, rejected alternatives, + unresolved questions safe for FCP, staged implementation plan, conformance/fitness gates, + docs/scaffold implications, and issue/epic decomposition. +3. Treat Claude's prose as a design pack to challenge. Cite repository paths/symbols and primary + upstream sources where relevant. Use focused type probes or non-product scratch proofs when they + materially validate inference/ergonomics; do not implement framework code in this RFC PR. +4. Make an initial harness/bootstrap commit, push only with an explicit refspec, and open a draft PR + against `main` in the same session. The PR must reference `#1348` without closing it, carry `rfc`, + `type:docs`, `area:sdk`, `area:plugins`, `priority:p1`, `ci:skip-e2e`, `ci:skip-scaffold`, and + exactly one lifecycle status. Move it to `status:plan-eval` only when the RFC is ready for Fable + review. Never assign an RFC number, merge, create/close issues, or mutate milestones. +5. Commit in coherent slices with run-artifact updates and PR phase comments. Run the docs/RFC gates + that actually apply and record exact evidence. Do not trigger PLAN-EVAL/IMPL-EVAL yourself: the + root orchestrator will steer the existing Claude Fable 5 session for the cross-RFC review, then + run the final Qwen adversarial pass. +6. Finish with a concise `final-handoff.md` containing PR URL/number, HEAD SHA, run-dir path, + decisions made, unresolved questions, validation evidence, board reconciliation proposal, and + exact instructions for the Fable reviewer. Then report back to the root orchestrator. + +Quality bar: this must be a real architecture RFC that a maintainer can ratify and an implementer +can execute without guessing—not a lightly edited copy of Claude's draft. Preserve NetScript's +mission: maximum end-to-end type safety, thin composable seams, generated ergonomics, plugin-owned +extensions, observable failure, and no hidden magic. + diff --git a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/plan.md b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/plan.md new file mode 100644 index 0000000000..f2b583f3b5 --- /dev/null +++ b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/plan.md @@ -0,0 +1,118 @@ +# Plan: typed SDK client contribution RFC + +## Run Metadata + +| Field | Value | +| --- | --- | +| Run ID | `docs-rfc-sdk-client-contribution--rfc` | +| Branch | `docs/rfc-sdk-client-contribution` | +| Phase | `research` | +| Target | `rfcs/0000-sdk-client-contributions.md` plus harness evidence | +| Archetype | `2 Integration`; `4 Public DSL / Builder`; `5 Plugin`; `6 CLI / Tooling` (described implementation surfaces) | +| Scope overlays | `SCOPE-docs` | + +## Archetype + +This is a docs-only RFC run whose proposed implementation crosses existing packages with different +assigned archetypes. The RFC must therefore carry the union of their design constraints and future +gates without pretending the RFC PR itself is a framework-source wave. + +## Current Doctrine Verdict + +- `@netscript/sdk` and `@netscript/contracts`: **Keep**. +- `@netscript/service`: **Refactor** (open role-clarification debt; the RFC must not deepen it). +- `@netscript/plugin`: historical **Restructure** is closed except the open builder-size debt. +- `@netscript/telemetry`: historical **Refactor** is closed, with separate compatibility debt still + open for domain-specific instrumentation. +- First-party plugins remain thin delivery shells under doctrine 11. + +## Goal + +Produce the lightweight, decision-complete NetScript RFC for a minimal typed SDK client +contribution axis, grounded in the current repository and upstream oRPC rather than the carried-in +proposal. + +## Scope + +- Re-baseline source, type, export, test, docs, issue/PR, and upstream claims. +- Lock the public/type-level contract, composition law, failure model, security/redaction boundary, + plugin discovery relationship, generated ergonomics, compatibility, migration, and gates. +- Prove generality with auth plus a non-auth consumer using focused scratch type probes where useful. +- Produce the draft RFC and complete run artifacts; no framework-source implementation. + +## Non-Scope + +- No package/plugin/CLI implementation, RFC numbering, merge, issue creation/closure, milestone + mutation, evaluator launch, or release gate. + +## Hidden Scope + +- Full JSR/export consequences of proposed type parameters and subpaths. +- Board reconciliation against already-filed issues `#1348`–`#1353` without mutating them. +- Explicit upstream oRPC version/surface citations and inference-budget constraints. + +## Locked Decisions + +Decisions are not locked at bootstrap. They will be derived in research and recorded before the +external Plan & Design review handoff. + +## Open-Decision Sweep + +All design forks named by the brief are `must resolve now` unless the final RFC proves they are safe +for FCP without forcing implementation rework. + +## Risk Register + +| Risk | Mitigation | +| --- | --- | +| Carried-in design invents a parallel abstraction or leaks upstream internals. | Start from current public types and `deno doc`; minimize to named extension axes under A11. | +| Tuple/context inference becomes slow, unstable, or inscrutable. | Focused type probes; explicit inference budget and `isolatedDeclarations`/JSR gate plan. | +| Auth special-casing masquerades as generality. | Require a structurally different second consumer and negative/removal proof. | +| Security metadata or credentials leak into logs, errors, or browser bundles. | Specify taint/redaction ownership, server-only boundaries, and conformance tests. | +| RFC over-claims board ownership. | Reconcile live issue/PR scope and retain references without closing keywords or mutations. | + +## Anti-Patterns to Resolve or Avoid + +| AP | Status | Plan | +| --- | --- | --- | +| AP-9 premature abstraction | risk | Name the exact extension axes and reject fields without two proven consumers or upstream necessity. | +| AP-11 hidden globals | risk | Require per-call context/resolvers; prohibit module-scope credential reads and mutable registries. | +| AP-14 upstream re-export | risk | Use NetScript-owned public contracts; do not re-export oRPC as NetScript API. | +| AP-24 closed switch / host hardcoding | existing risk | Keep discovery and contribution registration open-on-package, deterministic, and conflict-checked. | +| AP-25 side effects outside edges | risk | Place transport and secret resolution at explicit adapter/request boundaries. | + +## Fitness Gates + +The exact docs/RFC gate set will be locked after source/export research. Framework implementation +issues will inherit the applicable F-1–F-19, JSR, consumer, plugin-parity, CLI/scaffold, and runtime +gates for Archetypes 2/4/5/6; this docs PR will run source-alignment, link/path, terminology, +Markdown formatting, and relevant docs build/link gates. + +## Arch-Debt Implications + +No debt entry is expected for a docs-only RFC. Existing service/plugin/telemetry/auth debt will be +cited where it constrains implementation; any newly discovered divergence will be recorded before +handoff rather than silently added to product scope. + +## Validation Plan + +| Order | Gate | Command or check | Expected result | +| --- | --- | --- | --- | +| 1 | Source/API alignment | `deno doc` plus focused code/tests/exports inspection | Every prescriptive claim grounded | +| 2 | Type ergonomics | Non-product `.llm/tmp/` Deno type probes | Intended inference and rejection cases compile/fail as specified | +| 3 | RFC/docs integrity | repo-native docs/link/format checks selected from current tasks | Exit 0 or scoped N/A with evidence | +| 4 | JSR consequences | full export-map doc/audit inspection for affected packages | Risks and required implementation gates explicit | +| 5 | GitHub reconciliation | live issue/PR reads | No stale scope/state claims; no mutation beyond the draft PR | + +## Dependencies + +- Tracking issue `#1348`, implementation issues `#1349`–`#1353`, source roadmap PR `#1347`, and + live dependencies identified by those artifacts. +- Current pinned oRPC public surface and primary upstream documentation/source. + +## Drift Watch + +- Any mismatch between proposal citations and `origin/main`. +- Any filed issue whose actual scope differs from the proposal's T1 mapping. +- Any upstream oRPC surface that makes a proposed wrapper redundant or unsound. + diff --git a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/research.md b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/research.md new file mode 100644 index 0000000000..d6ad5388e5 --- /dev/null +++ b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/research.md @@ -0,0 +1,38 @@ +# Research — docs-rfc-sdk-client-contribution--rfc + +## Re-baseline + +- Carried-in source: + `/home/codex/repos/netscript-fable5-remediation-plan/.llm/runs/plan-fable5-remediation-roadmap--seed/fable-5-remediation-plan/rfcs/RFC-A-sdk-client-composition.md` +- Re-derived against `origin/main` @ `fac9e339042c5394bf882311657d8981d353a1c3` on 2026-08-08. +- Status: in progress. The 755-line proposal has been read as a challengeable design pack, not as + repository truth. Current exports, consumers, tests, issues/PRs, and upstream oRPC sources remain + to be re-verified before decisions are locked. + +## Findings + +| # | Finding | How to verify | +| - | ------- | ------------- | +| 1 | The requested branch starts exactly at the requested baseline, and freshly fetched `origin/main` remains at that SHA. | `git rev-parse HEAD origin/main`; `git merge-base HEAD origin/main` | +| 2 | The RFC process requires a `rfcs/0000-*.md` draft; a maintainer assigns a number only at acceptance. | `rfcs/README.md`; `rfcs/0000-template.md` | +| 3 | This RFC describes Archetype 2, 4, 5, and 6 consequences under the docs overlay; the PR itself will not change framework source. | doctrine 06/11; selected harness profiles; task brief | +| 4 | Current doctrine treats `@netscript/sdk`, `@netscript/contracts`, `@netscript/service`, and `@netscript/plugin` as Archetype 4; telemetry/auth cores as Archetype 2; first-party plugins as Archetype 5; CLI/scaffolding as Archetype 6. | `docs/architecture/doctrine/06-archetypes.md` | + +## jsr-audit surface scan (package/plugin waves) + +- Surface to scan: the current full export maps and docs for `packages/sdk`, `packages/contracts`, + `packages/service`, `packages/plugin`, the selected auth/telemetry consumer packages, and any + RFC-proposed new subpaths. +- Slow-type / surface risks: generic tuple-to-intersection inference, exported upstream-bound oRPC + types, `isolatedDeclarations`, entrypoint documentation, consumer import stability, and publish + file/subpath boundaries. +- Status: pending `deno doc`, export-map inspection, and focused publish-surface audit. + +## Open questions + +- Which smallest contribution contract survives both an auth and a structurally different non-auth + consumer without exposing unstable upstream or experimental types? +- Which proposal claims are stale or over-broad on current `main` and live GitHub state? +- Which choices must be ratified now versus remain safe FCP questions without implementation + rework? + diff --git a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/supervisor.md b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/supervisor.md new file mode 100644 index 0000000000..b35d6d64eb --- /dev/null +++ b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/supervisor.md @@ -0,0 +1,35 @@ +# Supervisor Identity — docs-rfc-sdk-client-contribution--rfc + +Written at run start per `workflow/lane-policy.md` § Supervisor identity. + +| Field | Value | +| --- | --- | +| Model | Codex · OpenAI · GPT-5.6 Sol · xhigh | +| Session | `019fe242-2bd9-7ff3-8044-bd9d09585397` | +| Host | native WSL Linux · user `codex` · full-access / approval `never` | +| Checkout | `/home/codex/repos/ns-rfc-sdk-client` | +| Worktree | `/home/codex/repos/ns-rfc-sdk-client` | +| Branch | `docs/rfc-sdk-client-contribution` (no upstream by design) | +| Baseline | `origin/main` @ `fac9e339042c5394bf882311657d8981d353a1c3` (verified 2026-08-08) | +| Run ID | `docs-rfc-sdk-client-contribution--rfc` | + +## Routes in force + +| Task lane | Provider / model / effort | Role in this run | +| --- | --- | --- | +| Owner-directed RFC generator | OpenAI / GPT-5.6 Sol / xhigh | Sole researcher and RFC author; daemon-attached session above | +| Owner-directed cross-RFC review | Existing Anthropic / Claude Fable 5 session; identity to be recorded by root orchestrator | Separate-session RFC/plan review after generator handoff; this session must not launch it | +| Owner-directed final adversarial pass | Qwen route selected and launched by root orchestrator | Separate-session final review after Fable; this session must not launch it | + +## Recorded lane/eval overrides + +- The owner explicitly selected Sol xhigh for sole RFC authorship instead of the default + documentation-authoring lane. +- The owner explicitly reserved cross-RFC review for an existing Claude Fable 5 session and a later + Qwen adversarial pass. This generator will prepare the artifacts and stop at `status:plan-eval`; + it will not trigger PLAN-EVAL or IMPL-EVAL. +- `.llm/tools/agentic/runtime status` reported `MISSING_IDENTITY` because the already-active desktop + thread is not registered as a runtime-controller session. The launch-generated + `codex-thread-ids.md` and rollout path provide the concrete daemon-attached identity; no daemon + repair or rival launch is authorized. + diff --git a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/worklog.md b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/worklog.md new file mode 100644 index 0000000000..ad191739d7 --- /dev/null +++ b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/worklog.md @@ -0,0 +1,96 @@ +# Worklog: typed SDK client contribution RFC + +## Run Metadata + +| Field | Value | +| --- | --- | +| Run ID | `docs-rfc-sdk-client-contribution--rfc` | +| Branch | `docs/rfc-sdk-client-contribution` | +| Archetype | `2 + 4 + 5 + 6` described; docs-only PR | +| Scope overlays | `SCOPE-docs` | + +## Design + +This Design checkpoint is intentionally bootstrap-level. It records the artifact and decision +vocabulary before RFC authoring; exact public types and composition laws will replace the pending +items after research and before `status:plan-eval`. + +### Public Surface + +- `rfcs/0000-sdk-client-contributions.md` — proposed public SDK/plugin contract; no product export + is added by this PR. +- Pending RFC types/functions: contribution descriptor, definition helper, client-option generic, + composition/failure types, and plugin declaration carrier. + +### Domain Vocabulary + +- **Contribution** — a named, versioned client-construction descriptor supplied explicitly or by a + plugin declaration. +- **Contribution chain** — an immutable ordered tuple whose fold yields one client configuration + and one inferred per-call context. +- **Reserved owner** — the framework or first contribution that exclusively owns a conflicting + field/key. +- **Sensitive value** — credential/header/context data whose diagnostics must retain metadata but + redact value material. + +### Ports + +- No product port is introduced in this docs PR. The RFC must decide whether the current client-link + seam is sufficient and what transport ownership remains framework-only. + +### Constants + +- RFC number remains `0000` until maintainer acceptance. +- Contribution contract version and finite error codes remain pending research; the RFC will name + them only if their stability value exceeds their compatibility cost. + +### Commit Slices + +| # | Slice | Gate | Files | +| - | ----- | ---- | ----- | +| 1 | Activate run identity and evidence skeleton | direct artifact/path review + git status | `.llm/runs/docs-rfc-sdk-client-contribution--rfc/*` | +| 2 | Lock re-baselined research and RFC design | source/API citations + type probes + Plan-Gate checklist | `research.md`, `plan.md`, `worklog.md`, `context-pack.md`, `drift.md`, `rfcs/0000-sdk-client-contributions.md` | +| 3 | Prove docs/JSR/GitHub readiness and hand off | applicable docs/RFC gates + live PR metadata reconciliation | RFC, run artifacts, `final-handoff.md`, draft PR body/comments/labels | + +### Deferred Scope + +- Framework implementation and migrations — separate post-acceptance issues/PRs. +- RFC number and decision state beyond Draft — maintainer-owned lifecycle. +- Formal/cross-RFC evaluator execution — root orchestrator owns existing external sessions. + +### Contributor Path + +Read the accepted RFC's terminology and invariants, then follow its staged issue decomposition: +contract/type surface first, composition/runtime second, two first-party consumer proofs third, +generated/scaffold ergonomics and documentation last. + +## Progress Log + +| Time | Slice | Step | Notes | +| --- | --- | --- | --- | +| 2026-08-08 | 1 | bootstrap | Read requested skills, RFC process, harness workflow/gates/evaluator protocols, selected archetypes, doctrine 01–11, relevant debt, and the full carried-in proposal. | +| 2026-08-08 | 1 | identity | Verified exact branch/base, clean tracked tree, daemon launch artifact, native WSL path, explicit-refspec rule, and valid GitHub credential. | + +## Decisions + +| Decision | Reason | Source | +| --- | --- | --- | +| Treat RFC authorship as Plan & Design, not framework implementation. | The deliverable is the ratifiable plan; no product code is authorized. | `rfcs/README.md`; task brief; harness run loop | +| Use Archetypes 2/4/5/6 plus `SCOPE-docs`. | Those are the current assigned profiles of the implementation surfaces the RFC describes. | doctrine 06/11; harness archetypes | +| Do not launch or repair a session. | The existing thread is proven and the owner forbids a rival; runtime-controller registration absence does not imply daemon failure. | `codex-thread-ids.md`; codex-wsl-remote skill | + +## Drift + +| Drift | Severity | Logged in drift.md | +| --- | --- | --- | +| Runtime controller did not match the launch-generated active thread identity. | minor | yes | + +## Gate Results + +Gate execution begins after RFC authoring; bootstrap evidence is recorded above. + +## Handoff Notes + +- External reviewers should challenge whether each proposed field has a named extension axis and + whether both first-party proofs exercise it. + From 89ae608ea935ba8b2776d55e7cb5a09cc29e2520 Mon Sep 17 00:00:00 2001 From: Rickylabs Date: Sat, 8 Aug 2026 19:33:27 +0200 Subject: [PATCH 02/12] docs(rfc): specify typed sdk client contributions --- .../context-pack.md | 155 ++- .../drift.md | 42 + .../plan.md | 218 ++-- .../research.md | 210 +++- .../worklog.md | 214 +++- rfcs/0000-sdk-client-contributions.md | 1074 +++++++++++++++++ 6 files changed, 1692 insertions(+), 221 deletions(-) create mode 100644 rfcs/0000-sdk-client-contributions.md diff --git a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/context-pack.md b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/context-pack.md index 0b1718f0f6..93e03ba6e4 100644 --- a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/context-pack.md +++ b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/context-pack.md @@ -2,72 +2,107 @@ ## Run Metadata -| Field | Value | -| --- | --- | -| Run ID | `docs-rfc-sdk-client-contribution--rfc` | -| Branch | `docs/rfc-sdk-client-contribution` | -| Current phase | `research` | -| Archetype | `2 + 4 + 5 + 6` described; docs-only PR | -| Scope overlays | `SCOPE-docs` | +| Field | Value | +| -------------- | ---------------------------------------------------------------------- | +| Run ID | `docs-rfc-sdk-client-contribution--rfc` | +| Branch | `docs/rfc-sdk-client-contribution` | +| Current phase | RFC authored; final evidence/reconciliation before `plan-eval` handoff | +| Archetype | `2 + 4 + 5 + 6` described; docs-only PR | +| Scope overlays | `SCOPE-docs` | +| PR | `https://github.com/rickylabs/netscript/pull/1390` | ## Current State -The harness run is activated on the exact requested base. Required skills, RFC process, harness -authorities, doctrine, selected archetypes, relevant debt, and the complete carried-in RFC-A design -pack have been read. No product code or RFC draft has yet been authored. - -## Completed - -- Exact base/worktree/session/GitHub-auth verification. -- Harness/doctrine/RFC authority read and archetype/overlay selection. -- Bootstrap artifact creation while preserving the launch-generated `implement.md` and - `codex-thread-ids.md`. - -## In Progress - -- Initial bootstrap commit, explicit-refspec push, and draft PR opening. - -## Next Steps - -1. Open the draft PR with the required labels and `status:research`. -2. Re-baseline live issues/PRs and current public/export/test surfaces through `deno doc` and - focused source reads. -3. Run type probes and upstream primary-source research; lock design and author the RFC. - -## Key Decisions - -| Decision | Source | Notes | -| --- | --- | --- | -| Keep `0000` and Draft state. | `rfcs/README.md` | Maintainer assigns number at acceptance. | -| Stop at external review handoff. | Owner brief | Generator must not trigger evaluator sessions. | -| No framework source in this PR. | Owner brief | Type probes live only under ignored/non-product `.llm/tmp/`. | +The RFC is authored at `rfcs/0000-sdk-client-contributions.md` and keeps `0000`/Draft. It rejects +the starting single “everything” envelope and ratifies a narrow, versioned request-header +preparation axis. Research, type proof, current JSR/doc-lint baselines, live board state, and +primary upstream sources are recorded. No product source is changed. + +## Decision Snapshot + +- `defineSdkClientContribution()` produces a named major-1 descriptor with a runtime + required/optional context declaration, exclusive lower-case header ownership, mandatory cache + effect, and async `prepare`. +- Literal tuples intersect context and diagnose duplicate id/context/header ownership; runtime + repeats checks. Limit: 16 contributions/service. +- Each contributor sees the same immutable snapshot; successful composition is order-independent. +- Query-safe contributions are `invariant` or supply a synchronous non-secret id-sorted partition. + `direct-only` service keys are omitted from generated query maps. +- Bearer auth is the first dogfood in `plugin-auth-core`; locale/`accept-language` is the non-auth + proof. +- `NetScriptProcedureMeta.access.authentication` is `none | optional | required`; unmarked auth + defaults to `none`. +- SDK transport retains discovery/codec/fetch/retry/dedupe/trace/errors. Trace fields are reserved; + #1353 is a trace-ownership proof, not a contribution. +- Plugin discovery registers static module/export/targets; generated/app config explicitly selects + contributions per service. +- Preparation failures are stable local errors, never server-defined contract errors. ## Files Changed -| Path | Status | Notes | -| --- | --- | --- | -| `.llm/runs/docs-rfc-sdk-client-contribution--rfc/` | new | Mandatory run artifacts plus existing launch records | - -## Gates - -| Gate family | Current status | Evidence | -| --- | --- | --- | -| Static | pending | after RFC draft | -| Fitness | planning | union selected from Archetypes 2/4/5/6; docs PR gates to be locked | -| Runtime | N/A for RFC PR | no runtime implementation | -| Consumer | research pending | API/type probes and current consumers | - -## Open Questions - -- All design forks in the task brief remain open until the re-baseline is complete. - -## Drift and Debt - -- Drift: runtime-controller identity miss recorded in `drift.md`; launch artifact remains the - concrete session proof. -- Debt: no new debt; relevant existing entries are summarized in `plan.md`. +| Path | Status | Notes | +| -------------------------------------------------- | --------------- | ----------------------------------------------------- | +| `rfcs/0000-sdk-client-contributions.md` | new | Decision-complete RFC; no product implementation. | +| `.llm/runs/docs-rfc-sdk-client-contribution--rfc/` | updated/new | Mandatory harness evidence plus launch records. | +| `.llm/tmp/sdk-client-contribution-probe.ts` | ignored scratch | Non-product inference/conflict proof; not part of PR. | + +## Live Board Snapshot + +- #1348 is open `status:triage`, milestone 0.0.6; it remains tracking and needs post-FCP body + reconciliation. +- #1349–#1353 are open `status:triage`, milestone 0.0.7. +- #1093 is generic discovery; #451 remains sole custom-link owner. +- #928/#934 align protocol/metadata vocabulary at 0.0.9; #884 is a later tenant candidate. +- PR #1347 remains an open draft planning record and says it must not merge. +- No issue/milestone was mutated by this run. + +## Gate Snapshot + +| Gate | Status | Evidence | +| ------------------------------ | ---------------- | ------------------------------------------------------------------------------- | +| RFC formatting | pass | `deno fmt --check` | +| RFC internal links | pass | focused repo link checker, 0 broken | +| Repository docs links/accuracy | pass | both tasks exit 0 | +| Type probe | pass | Deno check; 16 accepted/17 rejected fixture | +| Package dry-run baseline | pass | contracts/sdk/plugin/auth-core all report dry-run OK | +| JSR package audit | baseline finding | plugin audit exit 1 on pre-existing module tags/cardinality; other three exit 0 | +| Doc-lint baseline | baseline finding | combined private refs 9/3/15/4 respectively; RFC adds none | +| Doctrine | pass | `deno task arch:check` exits 0; existing warnings are baseline | +| Plan Gate self-audit | pass | complete for external evaluator entry; no evaluator verdict claimed | +| Final PR reconciliation | pending | slice 3 | + +## JSR Consequences + +- No new contracts/SDK/plugin subpaths; root/client/ports/config symbols expand. +- Auth core adds `./sdk` and possibly a constrained `./sdk/server` export. +- No oRPC public type may leak into declarations. +- Implementation must reduce or isolate existing private-type references, preserve precise error and + metadata types, and pass doc-lint/publish/consumer gates. + +## Board Reconciliation Proposal (no mutation yet) + +1. Amend #1348 acceptance to the narrow header/context/cache law after RFC acceptance. +2. Narrow #1349 to descriptor/composer/context/query-safety work. +3. Keep #1350 exact error/metadata repair and #1351 SDK-owned transport consolidation. +4. Place bearer convention in auth core under #1352. +5. Re-scope #1353 to final trace injection/reserved-key conformance. +6. File a locale proof child only after acceptance. +7. Cross-link #1093 and keep #451 independent. + +## External Reviewer Entry Point + +Read, in order: + +1. `rfcs/0000-sdk-client-contributions.md`; +2. `research.md` proposal challenge and API/board evidence; +3. `plan.md` locked decisions, gates, and issue reconciliation; +4. `worklog.md` Design and gate results; and +5. `drift.md` for owner-authorized evaluator routing and design drift. + +The reviewer must not implement product code, assign an RFC number, merge, close issues, or mutate +milestones. Findings should cite RFC headings and classify blocking versus safe FCP feedback. ## Commits -- See the draft PR's commit list + per-slice PR comments (V3 retired `commits.md`). - +- Bootstrap: `158849031bba78025d0ec16c8361628211fbc4ed`. +- Later commits and per-slice PR comments are the authoritative V3 commit record. diff --git a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/drift.md b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/drift.md index c998455c3b..638c83e447 100644 --- a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/drift.md +++ b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/drift.md @@ -31,3 +31,45 @@ documentation. - **Action:** stop at `status:plan-eval`, provide exact reviewer instructions, and let the root orchestrator record observed evaluator identities/verdicts. - **Evidence:** `implement.md` § Required output 5; `supervisor.md` routes table. + +## 2026-08-08 — Proposed trace contribution conflicts with current span ownership + +- **What:** The carried-in proposal and #1353 choose trace propagation as the second contribution, + but the current HTTP link creates the CLIENT span inside its `fetch` callback and injects that + span's trace context into the final request. +- **Source:** carried-in RFC-A §9; `packages/sdk/src/client/http-client-link.ts`; W3C Trace Context. +- **Expected:** A second non-auth consumer would exercise the same ratified preparation seam. +- **Actual:** Preparing `traceparent` before the client span either produces the wrong parent or is + overwritten by transport injection. +- **Severity:** significant design drift. +- **Action:** reserve `traceparent`/`tracestate`, keep trace transport-owned, re-scope #1353 to a + conformance proof, and use locale/`accept-language` as the non-auth contribution. +- **Evidence:** RFC “Transport ownership and oRPC alignment” and rejected-alternatives sections. + +## 2026-08-08 — Proposal omitted response-cache identity for contributed context + +- **What:** The proposal threads auth/trace context and allows query behavior but does not prove + that identical procedure input under two credentials/locales cannot share existing server or + TanStack cache entries. +- **Source:** current `query-factory.ts`, `query-key.ts`, `service-query-utils.ts`, and upstream + TanStack query option types. +- **Expected:** End-to-end typed context would remain safe through generated query paths. +- **Actual:** Current full keys do not contain client context; blindly forwarding it permits + cross-principal/representation reuse. +- **Severity:** significant design drift and security risk. +- **Action:** require every contribution to declare `invariant`, synchronous non-secret + `partitioned`, or `direct-only`; omit unsafe generated query maps. +- **Evidence:** RFC “Query and generated type propagation”; `research.md` findings 5–7. + +## 2026-08-08 — Current JSR/doc-lint baseline is not clean + +- **What:** Repository-native audits report publish dry-run success but existing private-type-ref, + module-tag, cardinality, and slow-type findings in packages the implementation would touch. +- **Source:** `audit-jsr-package.ts` and `run-deno-doc-lint.ts` on contracts/sdk/plugin/auth-core. +- **Expected:** A clean doc/publish baseline would let future failures be attributed directly. +- **Actual:** combined private-type refs are 9/3/15/4; plugin audit exits 1 on four existing + module-tag failures plus cardinality warnings; all four publish dry-runs still report OK. +- **Severity:** baseline debt/evidence; not caused by this docs PR. +- **Action:** record exact baseline, forbid new regressions, and require #1350/contribution work to + reduce or isolate private upstream refs rather than invoking the current baseline as a waiver. +- **Evidence:** `research.md` JSR section; `worklog.md` gate table. diff --git a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/plan.md b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/plan.md index f2b583f3b5..d253c95f91 100644 --- a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/plan.md +++ b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/plan.md @@ -2,117 +2,191 @@ ## Run Metadata -| Field | Value | -| --- | --- | -| Run ID | `docs-rfc-sdk-client-contribution--rfc` | -| Branch | `docs/rfc-sdk-client-contribution` | -| Phase | `research` | -| Target | `rfcs/0000-sdk-client-contributions.md` plus harness evidence | -| Archetype | `2 Integration`; `4 Public DSL / Builder`; `5 Plugin`; `6 CLI / Tooling` (described implementation surfaces) | -| Scope overlays | `SCOPE-docs` | +| Field | Value | +| -------------- | ------------------------------------------------------------------------------------------------------------ | +| Run ID | `docs-rfc-sdk-client-contribution--rfc` | +| Branch | `docs/rfc-sdk-client-contribution` | +| Phase | RFC authored; evidence/gates and external-review handoff remain | +| Target | `rfcs/0000-sdk-client-contributions.md` plus mandatory harness artifacts | +| Archetype | `2 Integration`; `4 Public DSL / Builder`; `5 Plugin`; `6 CLI / Tooling` (described implementation surfaces) | +| Scope overlays | `SCOPE-docs` | ## Archetype This is a docs-only RFC run whose proposed implementation crosses existing packages with different -assigned archetypes. The RFC must therefore carry the union of their design constraints and future -gates without pretending the RFC PR itself is a framework-source wave. +assigned archetypes. The RFC carries the union of their design constraints and future gates without +claiming that this PR implements framework code. ## Current Doctrine Verdict -- `@netscript/sdk` and `@netscript/contracts`: **Keep**. -- `@netscript/service`: **Refactor** (open role-clarification debt; the RFC must not deepen it). -- `@netscript/plugin`: historical **Restructure** is closed except the open builder-size debt. -- `@netscript/telemetry`: historical **Refactor** is closed, with separate compatibility debt still - open for domain-specific instrumentation. -- First-party plugins remain thin delivery shells under doctrine 11. +- `@netscript/sdk` and `@netscript/contracts`: **Keep**; add a package-owned type surface, not an + upstream mirror. +- `@netscript/service`: **Refactor**; do not deepen its preset/primitive ambiguity by adding server + plugin fields to a client descriptor. +- `@netscript/plugin`: historical **Restructure** is closed except current debt; add an open generic + reference group and reject host switches. +- `@netscript/telemetry`: **Keep** at the transport boundary; final trace injection remains owned by + the SDK adapter. +- `@netscript/plugin-auth-core`: integration/core owner of bearer conventions; `plugins/auth` + remains a thin delivery shell. ## Goal -Produce the lightweight, decision-complete NetScript RFC for a minimal typed SDK client -contribution axis, grounded in the current repository and upstream oRPC rather than the carried-in -proposal. +Produce the lightweight, decision-complete NetScript RFC for a minimal typed SDK client contribution +axis, grounded in the current repository and public upstream oRPC behavior. ## Scope -- Re-baseline source, type, export, test, docs, issue/PR, and upstream claims. -- Lock the public/type-level contract, composition law, failure model, security/redaction boundary, - plugin discovery relationship, generated ergonomics, compatibility, migration, and gates. -- Prove generality with auth plus a non-auth consumer using focused scratch type probes where useful. -- Produce the draft RFC and complete run artifacts; no framework-source implementation. +- Re-baseline source, type, export, test, docs, issue/PR, standard, and upstream claims. +- Lock the public/type contract, context and cache algebra, composition law, failure model, + security/redaction boundary, plugin discovery, generated ergonomics, compatibility, migration, + decomposition, and gates. +- Prove generality with auth plus a structurally different locale contribution. +- Produce the draft RFC and complete run artifacts; no framework implementation. ## Non-Scope - No package/plugin/CLI implementation, RFC numbering, merge, issue creation/closure, milestone - mutation, evaluator launch, or release gate. + mutation, evaluator launch, release gate, or custom transport API. -## Hidden Scope +## Hidden Scope resolved -- Full JSR/export consequences of proposed type parameters and subpaths. -- Board reconciliation against already-filed issues `#1348`–`#1353` without mutating them. -- Explicit upstream oRPC version/surface citations and inference-budget constraints. +- JSR/export consequences of recursive public types and the new auth-core subpath. +- Safe response-cache identity across direct, server-query, and TanStack paths. +- Board reconciliation against #1348–#1353, #1093, #451, #928, #934, and #884 without mutation. +- Current oRPC lock/stable state and an explicit inference ceiling. ## Locked Decisions -Decisions are not locked at bootstrap. They will be derived in research and recorded before the -external Plan & Design review handoff. +| Axis | Decision | +| ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Extension axis | Request-header preparation from typed per-call context only. | +| Public protocol | Package-owned `{ family: 'netscript.sdk-client', major: 1 }`, named id, runtime context declaration, owned header names, mandatory response-cache effect, async `prepare`. | +| Context inference | Literal tuple intersection; required properties make request context required; named static conflicts plus runtime validation. | +| Ordering | Sequential deterministic evaluation of the same snapshot; contributors cannot observe accumulated output; valid results commute. | +| Conflict policy | Duplicate id/context/header or reserved/undeclared header is an error; never last-writer-wins. | +| Cache safety | `invariant`, synchronous non-secret `partitioned`, or `direct-only`; direct-only services have no generated query maps. | +| Auth | First-party bearer factory in auth core; per-call async resolver; unmarked metadata defaults to `none`; redacted stable failures. | +| Second consumer | Locale/`accept-language`, proving optional context and partitioned representation outside auth. | +| Metadata | `NetScriptProcedureMeta.access.authentication = "none" \| "optional" \| "required"`; unmarked procedures default to `"none"`. | +| Trace | Transport-owned and reserved; #1353 becomes trace-ownership conformance rather than a contribution. | +| Transport | Discovery/codec/fetch/retry/dedupe/trace/error remain SDK-owned; raw oRPC callbacks and links are not descriptor fields. #451 stays separate. | +| Query policy | No arbitrary defaults/invalidation callbacks; only canonical full-key partition suffix and context propagation. | +| Plugin discovery | Optional static module/export/target references; installation exposes availability, explicit generated config activates per service. | +| Inference budget | 16 contributions/service, 8 context keys/contributor, 16 header keys/contributor; type proof recorded. | +| Compatibility | Omitted tuple exactly preserves behavior/key shapes; old generic defaults remain; no-op `port`/`timeout` are deprecated but not removed here. | +| Error ownership | Stable local preparation error, not a server-defined error-map member. | ## Open-Decision Sweep -All design forks named by the brief are `must resolve now` unless the final RFC proves they are safe -for FCP without forcing implementation rework. +Every brief-named implementation fork is resolved in the RFC. Remaining questions are safe for FCP: + +1. a ceiling may be raised after CI type evidence but not lowered below 16; +2. server credential convenience export timing; +3. independent #451 scheduling; and +4. semantic-preserving public naming refinements. ## Risk Register -| Risk | Mitigation | -| --- | --- | -| Carried-in design invents a parallel abstraction or leaks upstream internals. | Start from current public types and `deno doc`; minimize to named extension axes under A11. | -| Tuple/context inference becomes slow, unstable, or inscrutable. | Focused type probes; explicit inference budget and `isolatedDeclarations`/JSR gate plan. | -| Auth special-casing masquerades as generality. | Require a structurally different second consumer and negative/removal proof. | -| Security metadata or credentials leak into logs, errors, or browser bundles. | Specify taint/redaction ownership, server-only boundaries, and conformance tests. | -| RFC over-claims board ownership. | Reconcile live issue/PR scope and retain references without closing keywords or mutations. | +| Risk | Mitigation / RFC gate | +| ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- | +| Parallel abstraction or upstream leakage | Descriptor maps only to native async headers; no public oRPC types; doc-lint and declaration inspection. | +| Tuple/context inference cost | Per-service tail recursion, 16 limit, named markers, type fixtures at 16/17. | +| Auth special case | Locale consumer and generic header/context/cache law; auth factory is one constrained implementation. | +| Cross-principal cache leak | Mandatory response-cache effect, id-sorted partition suffix, direct-only omission, two-principal tests. | +| Secret leakage | All values sensitive by default; fixed diagnostic allowlist; source failures discarded; redaction snapshots and OWASP baseline. | +| Trace breakage | Reserve trace keys and keep final injection at client-span transport edge. | +| Hidden plugin behavior | Static discovery and explicit per-service generated selection; duplicate/mismatch failures. | +| Board duplication | #451 sole custom-link owner; reconcile #1353 and add locale child only after acceptance. | + +## Anti-Patterns resolved + +| AP | Resolution | +| -------------------------------- | ----------------------------------------------------------------------------- | +| AP-9 premature abstraction | Reject every proposal field without necessity at the header/context boundary. | +| AP-11 hidden globals | Per-call resolver; no module-scope credential reads or global registries. | +| AP-14 upstream re-export | NetScript-owned descriptor/context/error/reference vocabulary only. | +| AP-24 closed switch | Generic `sdkClients` reference group and synthetic third-party gate. | +| AP-25 side effects outside edges | Secret resolution is per request; dispatch stays at the HTTP adapter. | + +## Implementation Contract (for future PRs) + +### Public surface first + +1. `NetScriptProcedureMeta` and exact base contract annotation. +2. Contribution descriptor/helper/type algebra and error diagnostic. +3. Client and query context generics with compatibility defaults. +4. Plugin static reference plus auth-core factory export. + +### Runtime second -## Anti-Patterns to Resolve or Avoid +1. Construction validation and reserved ownership. +2. Per-call preparation wrapper over the single oRPC header resolver. +3. Canonical cache partitions/direct-only map omission. +4. Redacted errors, abort/retry behavior, and transport integration. -| AP | Status | Plan | -| --- | --- | --- | -| AP-9 premature abstraction | risk | Name the exact extension axes and reject fields without two proven consumers or upstream necessity. | -| AP-11 hidden globals | risk | Require per-call context/resolvers; prohibit module-scope credential reads and mutable registries. | -| AP-14 upstream re-export | risk | Use NetScript-owned public contracts; do not re-export oRPC as NetScript API. | -| AP-24 closed switch / host hardcoding | existing risk | Keep discovery and contribution registration open-on-package, deterministic, and conflict-checked. | -| AP-25 side effects outside edges | risk | Place transport and secret resolution at explicit adapter/request boundaries. | +### Delivery third + +1. Auth and locale proofs. +2. Generic plugin discovery and generated explicit tuples. +3. Docs, scaffold, publish, and full CLI E2E gates. ## Fitness Gates -The exact docs/RFC gate set will be locked after source/export research. Framework implementation -issues will inherit the applicable F-1–F-19, JSR, consumer, plugin-parity, CLI/scaffold, and runtime -gates for Archetypes 2/4/5/6; this docs PR will run source-alignment, link/path, terminology, -Markdown formatting, and relevant docs build/link gates. +The RFC contains the full future gate matrix. This docs PR runs: -## Arch-Debt Implications +- Markdown formatting; +- focused RFC internal-link/path validation; +- repository docs links and accuracy; +- source/API/export and live-board alignment review; +- non-product type probe; +- current package JSR/doc-lint baseline scan; +- doctrine check and PR metadata/thread readiness where applicable. -No debt entry is expected for a docs-only RFC. Existing service/plugin/telemetry/auth debt will be -cited where it constrains implementation; any newly discovered divergence will be recorded before -handoff rather than silently added to product scope. +Framework implementation issues inherit type, runtime, redaction, cache isolation, plugin parity, +JSR/publish/consumer, CLI/scaffold, architecture, and full runtime E2E gates enumerated in the RFC. -## Validation Plan +## Arch-Debt Implications -| Order | Gate | Command or check | Expected result | -| --- | --- | --- | --- | -| 1 | Source/API alignment | `deno doc` plus focused code/tests/exports inspection | Every prescriptive claim grounded | -| 2 | Type ergonomics | Non-product `.llm/tmp/` Deno type probes | Intended inference and rejection cases compile/fail as specified | -| 3 | RFC/docs integrity | repo-native docs/link/format checks selected from current tasks | Exit 0 or scoped N/A with evidence | -| 4 | JSR consequences | full export-map doc/audit inspection for affected packages | Risks and required implementation gates explicit | -| 5 | GitHub reconciliation | live issue/PR reads | No stale scope/state claims; no mutation beyond the draft PR | +No new debt entry is required for a docs-only RFC. Existing private-type-ref and package cardinality +findings are baseline evidence, not waived by the RFC. Implementation must not add to them. Any +unavoidable new deviation requires a debt entry with owner/exit criteria in its own PR. -## Dependencies +## Validation Plan -- Tracking issue `#1348`, implementation issues `#1349`–`#1353`, source roadmap PR `#1347`, and - live dependencies identified by those artifacts. -- Current pinned oRPC public surface and primary upstream documentation/source. +| Order | Gate | Command/check | Expected result | +| ----- | -------------------- | ----------------------------------------------------------- | ------------------------------------------------------------------------------------- | +| 1 | Source/API alignment | `deno doc`, focused source/tests/exports, live GitHub reads | All prescriptive claims grounded. | +| 2 | Type ergonomics | ignored `.llm/tmp/` Deno type proof | Valid 16 tuple and required context pass; conflicts/17 fail under `@ts-expect-error`. | +| 3 | RFC integrity | `deno fmt --check`; focused link checker | Exit 0. | +| 4 | Repository docs | `deno task docs:links`; `deno task docs:accuracy` | Exit 0. | +| 5 | Publish consequences | package audit + structured doc-lint on four roots | Baseline recorded; no RFC source mutation. | +| 6 | Doctrine | `deno task arch:check` | Exit 0 or exact unrelated baseline recorded. | +| 7 | GitHub readiness | draft/labels/body/thread/commit verification | Required labels, one status, no milestone mutation/closing keyword. | + +## Plan Gate Self-Audit + +The RFC plan is ready for external evaluation: it states the current implementation and gap, +compares the broad proposal with the existing oRPC seam and narrower alternatives, locks public +placement and composition/failure/security laws, names migration and compatibility behavior, maps +implementation slices and issues, and defines executable fitness gates. The RFC carries no product +implementation and leaves only the four explicitly FCP-safe questions open. This is a generator +self-audit, not a PLAN-EVAL verdict; the owner-designated external reviewer remains authoritative. + +## Dependencies and Board Reconciliation + +- #1348 remains tracking/RFC record. +- #1349–#1352 retain implementation ownership with narrowed bodies. +- #1353 is re-scoped to trace transport ownership, not deleted. +- A locale proof child is proposed only after acceptance; none is filed in this run. +- #1093 supplies generic discovery. +- #451 remains the only custom-link issue. +- #928/#934 align on protocol/metadata vocabulary but do not block the minimal seam. ## Drift Watch -- Any mismatch between proposal citations and `origin/main`. -- Any filed issue whose actual scope differs from the proposal's T1 mapping. -- Any upstream oRPC surface that makes a proposed wrapper redundant or unsound. - +- Any review request that puts upstream callback arrays back in the descriptor. +- Any query path that receives auth/locale context without safe full-key partitioning. +- Any auth helper placed in the thin plugin rather than auth core. +- Any trace contributor that can author `traceparent`/`tracestate`. +- Any generated activation based only on installation or runtime scanning. diff --git a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/research.md b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/research.md index d6ad5388e5..88efd8164f 100644 --- a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/research.md +++ b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/research.md @@ -4,35 +4,183 @@ - Carried-in source: `/home/codex/repos/netscript-fable5-remediation-plan/.llm/runs/plan-fable5-remediation-roadmap--seed/fable-5-remediation-plan/rfcs/RFC-A-sdk-client-composition.md` -- Re-derived against `origin/main` @ `fac9e339042c5394bf882311657d8981d353a1c3` on 2026-08-08. -- Status: in progress. The 755-line proposal has been read as a challengeable design pack, not as - repository truth. Current exports, consumers, tests, issues/PRs, and upstream oRPC sources remain - to be re-verified before decisions are locked. - -## Findings - -| # | Finding | How to verify | -| - | ------- | ------------- | -| 1 | The requested branch starts exactly at the requested baseline, and freshly fetched `origin/main` remains at that SHA. | `git rev-parse HEAD origin/main`; `git merge-base HEAD origin/main` | -| 2 | The RFC process requires a `rfcs/0000-*.md` draft; a maintainer assigns a number only at acceptance. | `rfcs/README.md`; `rfcs/0000-template.md` | -| 3 | This RFC describes Archetype 2, 4, 5, and 6 consequences under the docs overlay; the PR itself will not change framework source. | doctrine 06/11; selected harness profiles; task brief | -| 4 | Current doctrine treats `@netscript/sdk`, `@netscript/contracts`, `@netscript/service`, and `@netscript/plugin` as Archetype 4; telemetry/auth cores as Archetype 2; first-party plugins as Archetype 5; CLI/scaffolding as Archetype 6. | `docs/architecture/doctrine/06-archetypes.md` | - -## jsr-audit surface scan (package/plugin waves) - -- Surface to scan: the current full export maps and docs for `packages/sdk`, `packages/contracts`, - `packages/service`, `packages/plugin`, the selected auth/telemetry consumer packages, and any - RFC-proposed new subpaths. -- Slow-type / surface risks: generic tuple-to-intersection inference, exported upstream-bound oRPC - types, `isolatedDeclarations`, entrypoint documentation, consumer import stability, and publish - file/subpath boundaries. -- Status: pending `deno doc`, export-map inspection, and focused publish-surface audit. - -## Open questions - -- Which smallest contribution contract survives both an auth and a structurally different non-auth - consumer without exposing unstable upstream or experimental types? -- Which proposal claims are stale or over-broad on current `main` and live GitHub state? -- Which choices must be ratified now versus remain safe FCP questions without implementation - rework? +- Repository authority: `origin/main` @ `fac9e339042c5394bf882311657d8981d353a1c3`, fetched and + re-verified on 2026-08-08. +- Live design record: draft PR `#1390` and tracking issue `#1348`. +- Result: the 755-line proposal is useful problem discovery, but its single envelope is too broad + for current code and doctrine. The ratifiable seam is typed request-header preparation plus the + minimum cache-variance declaration required to make query use safe. +## Authorities read completely + +- RFC process and template: `rfcs/README.md`, `rfcs/0000-template.md`. +- Harness: activation, run loop, lane policy, doc audit, gate matrix, plan gate, verdicts, and both + evaluator protocols. +- Profiles: `SCOPE-docs`, Archetypes 2, 4, 5, and 6. +- Doctrine: sections 01–11, including extension-axis law, public surfaces, layering, archetypes, + fitness gates, anti-patterns, debt, and plugin thinness. +- Relevant debt ledgers for SDK, contracts/service, plugin, telemetry, and auth. +- Requested skills: harness, doctrine, PR, tools, Deno toolchain, JSR audit, rtk, and WSL remote. + +## Current repository findings + +| # | Finding | Evidence and consequence | +| -- | ------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| 1 | The public client has no extension option. | `deno doc CreateServiceClientOptions packages/sdk/mod.ts` reports only `contract`, service/discovery fields, two reserved fields, and `propagateTraceContext`. | +| 2 | `port` and `timeout` are accepted but unused. | `packages/sdk/src/client/service-client.ts` destructures neither; `defineServices` forwards both. The RFC deprecates rather than repurposes them. | +| 3 | The HTTP link already owns the full transport policy. | `packages/sdk/src/client/http-client-link.ts` constructs the sole `RPCLink`, `Content-Type`, retry, GET dedupe, traced `fetch`, cache/signal forwarding, and final trace injection. | +| 4 | The useful header seam already exists upstream. | oRPC 1.14.6 declarations show `headers` is `Value, [ClientOptions, path, input]>`; no NetScript interceptor framework is necessary. | +| 5 | Client context is fixed and query layers erase it. | `ServiceClientContext`, `ServiceClientMethod`, `QueryFactory`, `ServiceQueryUtils`, and `invokeClientProcedure` have no context generic; `ServiceQueryClientContext` is forced to `Record`. | +| 6 | Upstream TanStack utilities already preserve required context. | `@orpc/tanstack-query@1.14.6` `QueryOptionsIn`, `InfiniteOptionsIn`, and `MutationOptionsIn` require context unless it is empty. NetScript's structural remap discards it. | +| 7 | Context-bearing headers create a cache-safety problem. | Current server and TanStack full keys contain input/path but no request context. Bearer/locale responses could collide unless the contribution declares response invariance or a non-secret partition. | +| 8 | A package-owned link port exists but is internal. | `packages/sdk/src/ports/client-link-factory.ts`; `ports/mod.ts` claims a transport seam but does not export it. Custom transport remains #451, not a contribution field. | +| 9 | Server handler plugins already have an axis. | `RPCHandlerConfig.plugins` and `createRPCPlugins` in `packages/service/src/primitives/handlers.ts`. Preset reachability is separate service work. | +| 10 | Plugin contributions need a generic SDK reference group. | `PluginContributions` has typed groups but no `sdkClients`; `cli.doctorChecks` is a closed `'auth-backend'[]` literal. #1093 is the generic-discovery dependency. | +| 11 | Contract metadata is supported upstream but not initialized by NetScript. | `deno doc ContractBuilder` shows `oc.$meta()`; actual `~orpc` definitions carry `meta`. `baseContract` currently starts at `oc.errors(...)`. | +| 12 | The current base annotation erases and leaks types. | `baseContract: ReturnType` is a current `deno doc --lint` private-type-ref and widens the error map. #1350 must preserve both concrete errors and new metadata. | +| 13 | Auth core, not the thin plugin, must own bearer conventions. | Doctrine 11 assigns convention-bearing primitives to `packages/plugin-auth-core`; `plugins/auth` should only declare/deliver the reference and wiring. | +| 14 | Trace headers are not a valid second request-preparation consumer. | The SDK creates a CLIENT span inside `fetch` and overwrites/injects `traceparent` there. Preparing it earlier would describe the wrong span or be overwritten. | + +## Current public API snapshots (`deno doc`) + +- `CreateServiceClientOptions`: 9 fields; no headers/context/link/plugin contribution. +- `ServiceClientContext`: signal/cache/retry/trace fields, all optional. +- `ServiceClientMethod`: input plus optional `ServiceRequestOptions`. +- `ServiceHandlerPlugin`: structural `order`, `init`, and `initRuntimeAdapter` using `unknown`. +- `RPCHandlerConfig`: already has `plugins`, tracing/error/dedupe/logging/debug fields. +- `PluginContributions`: 10 array groups plus `aspire` and `doctor` module strings; no SDK group. +- SDK module docs promise upstream-free `@netscript/sdk/ports`, constraining the RFC from exporting + oRPC link/interceptor types. + +## Live GitHub re-baseline + +| Artifact | Live state on 2026-08-08 | RFC consequence | +| -------- | --------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | +| PR #1347 | Open draft; planning record says it must not merge. | Cite as source roadmap only, not ratified architecture. | +| #1348 | Open, `status:triage`, milestone `0.0.6`. | RFC tracking record; this PR references but must not close it. Its body still assumes the broad envelope and needs post-FCP reconciliation. | +| #1349 | Open triage, milestone `0.0.7`. | Re-scope to minimal descriptor/context/header/query-safety seam; remove pass-through arrays/link scope. | +| #1350 | Open triage, milestone `0.0.7`. | Independent but coordinated base-contract error/metadata repair. | +| #1351 | Open triage, milestone `0.0.7`. | SDK-owned transport consolidation and coherent oRPC update; no contributor transport control. | +| #1352 | Open triage, milestone `0.0.7`. | Auth-core bearer dogfood, redaction, access metadata, cache partition/direct-only behavior. | +| #1353 | Open triage, milestone `0.0.7`. | Proposed trace dogfood conflicts with current span ownership; re-scope to transport trace conformance. | +| #1093 | Open triage, milestone `0.0.6`. | Generic plugin discovery is required for third-party module references. | +| #451 | Open research, Backlog / Triage. | Sole owner of a future custom-link option; it should unhide the existing port rather than extend this descriptor. | +| #928 | Open `status:plan`, milestone `0.0.9`. | Align on `(family, major)` negotiation vocabulary, not one universal contribution payload. | +| #934 | Open `status:plan`, milestone `0.0.9`. | May consume shared access metadata without depending on SDK contribution types. | +| #884 | Open triage, milestone `0.0.14`. | Future tenant contribution candidate; server org policy remains separate. | + +No issue, milestone, or lifecycle record was mutated in research. The PR is the only GitHub write. + +## Upstream and standards evidence + +| Source | Verified claim | +| ------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `deno.lock` and Deno cache declarations | The workspace resolves the oRPC family to 1.14.6. `ClientOptions` has signal/lastEventId/context; `RPCLinkOptions` composes native headers, link plugins, interceptors, and fetch capabilities. | +| `deno task deps:latest -- --filter '@orpc/*'` | Stable-channel report: seven oRPC packages are behind; `^1.14.6`/`^1.14.7` → `1.15.0` on 2026-08-08. Implementation must recheck rather than hardcode this future value. | +| `deno task deps:why -- @orpc/client` | Nine source hits; the dependency is live and not removable. | +| | Official docs show async headers from typed client context and method/fetch decisions from context/path. | +| | Official docs show `$meta()` initialization and procedure `~orpc.meta` consumption. | +| | Normative forbidden header list plus `proxy-`/`sec-` prefix ownership. | +| | Final trace mutation, privacy, and trust-boundary rules support transport ownership. | +| | HTTP credentials rely on secured transport for confidentiality. | +| OWASP Logging Cheat Sheet | Access tokens/session identifiers are excluded from direct logging. | + +## Proposal challenge record + +| Starting proposal choice | Verdict | Reason | +| ----------------------------------------------------------------------------------------------------------- | -------------------- | ----------------------------------------------------------------------------------------------------- | +| One envelope for headers, interceptors, plugins, fetch, link, errors, server plugins, metadata, and queries | Reject | Different owners/lifecycles; mirrors upstream; violates minimality and A14/AP14. | +| Named/versioned descriptor and tuple-derived context | Keep, narrow | Needed for plugin discovery, conflicts, generated typing, and unknown-boundary validation. | +| Later contribution overwrites declared header | Reject | Doctrine forbids semantic plugin-order dependence; all header owners are exclusive. | +| `requires`/priority/order fields | Reject in v1 | Contributors receive the same snapshot and cannot consume each other's output; valid results commute. | +| Trace as second contribution | Reject | Final trace header belongs to the client span created at transport dispatch. Reserve the keys. | +| Auth as first dogfood | Keep | Bearer resolution proves async secret/context/header/failure/redaction behavior. | +| Second proof | Change to locale | Locale is non-auth, owns a normal header, requires optional context, and proves cache partitioning. | +| Contribution error map merged with contract errors | Reject | Preparation failures occur before a server response and are not defined contract errors. | +| Arbitrary query defaults/invalidation | Reject | Existing query APIs remain policy owner; only a canonical cache-safety suffix is permitted. | +| Automatic plugin activation | Reject | Installation exposes availability; generated/app config explicitly selects per service. | +| Raw `fetch`/link override | Reject from this RFC | Transport remains SDK-owned; #451 owns future custom links using the existing structural port. | + +## Locked design conclusions + +1. Protocol `{ family: 'netscript.sdk-client', major: 1 }`; id is lower-case `:`. +2. Curried `defineSdkClientContribution()` validates a runtime context declaration with + required/optional modes, exclusive lower-case header keys, and one async `prepare` callback. +3. Patch surface is headers only. All emitted values are sensitive by default. +4. Literal tuples get named conflict diagnostics and a 16-contribution inference ceiling; runtime + repeats all checks. +5. Contributors execute sequentially with one immutable snapshot, cannot observe accumulated output, + and successful composition is order-independent. +6. Every contributor declares response cache as `invariant`, `partitioned`, or `direct-only`. + Partitions are synchronous/non-secret and sorted by id; direct-only services are omitted from + generated query maps. +7. `NetScriptProcedureMeta.access.authentication` is `none | optional | required`; first-party + bearer defaults unmarked procedures to `none`. +8. SDK transport owns discovery/codec/retry/dedupe/fetch/trace/errors. Trace fields and Fetch-owned + headers are reserved. +9. Plugin manifests carry static module/export/target references; generators use explicit imports + and literal tuples. No ambient activation. +10. No product implementation belongs in this RFC PR. + +## Type proof + +Ignored scratch proof: `.llm/tmp/sdk-client-contribution-probe.ts` with an isolated local config. + +Checked cases: + +- required auth plus optional locale context intersection; +- required request argument and missing-auth `@ts-expect-error`; +- named duplicate-context conflict at the tuple boundary; +- accepted 16-element synthetic tuple; and +- rejected 17-element tuple. + +Command: + +```text +deno check --config .llm/tmp/deno.json .llm/tmp/sdk-client-contribution-probe.ts +``` + +Result: exit 0. The first uncached observation was 0.67 s / 225,508 KiB RSS; a later warm check was +0.02 s / 27,136 KiB. Timing is informational, not a gate. + +## JSR / publish-surface audit + +### Current baseline + +The repository-native package audit reported dry-run OK for all four affected package roots: + +| Package | Exports now | Dry-run | Existing findings relevant to implementation | +| ----------------------------- | ----------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `@netscript/contracts` | 4 | OK | sanctioned oRPC slow-type warning; doc-lint reports 9 combined private-type refs. | +| `@netscript/sdk` | 12 | OK | slow-type warning and existing `src` cardinality warning; doc-lint reports 3 combined private-type refs. | +| `@netscript/plugin` | 13 | OK | 4 existing missing `@module` export docs plus cardinality warnings; doc-lint reports 15 combined private-type refs. Audit exits 1 on these pre-existing findings. | +| `@netscript/plugin-auth-core` | 9 | OK | slow-type warning; doc-lint reports 4 combined private-type refs. | + +Commands: + +```text +deno run -A .llm/tools/fitness/audit-jsr-package.ts --root --text +deno run --allow-read --allow-run .llm/tools/run-deno-doc-lint.ts --root --pretty +``` + +These are baseline findings, not caused by the RFC file. They make the implementation bar stricter: +new contribution types may not add private upstream refs or slow types, and #1350 must reduce rather +than deepen the contract leak. + +### Proposed publish consequences + +- `@netscript/contracts`: new root metadata types; no new subpath. +- `@netscript/sdk`: new root/client/ports symbols and generics; no new export subpath. +- `@netscript/plugin`: new optional config reference and builder path; no SDK runtime dependency. +- `@netscript/plugin-auth-core`: new `./sdk` export and optional explicit `./sdk/server` convenience + export; adds a reviewed SDK dependency. +- Generated declarations must remain package-owned and isolated-declaration compatible. +- Required implementation evidence: `deno doc --lint`, package audit, publish dry-run, packed/prod + consumer check, docs on every new entrypoint, and no `@orpc/*` type in emitted declarations. + +## Remaining safe questions + +- Whether to raise (never lower) the 16-contribution ceiling after CI evidence. +- Whether a server environment credential convenience export ships in the first auth slice. +- Whether #451 is rescheduled with this work while remaining independent. +- Final public naming refinements that preserve the locked semantics. diff --git a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/worklog.md b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/worklog.md index ad191739d7..ed968232c4 100644 --- a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/worklog.md +++ b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/worklog.md @@ -2,95 +2,193 @@ ## Run Metadata -| Field | Value | -| --- | --- | -| Run ID | `docs-rfc-sdk-client-contribution--rfc` | -| Branch | `docs/rfc-sdk-client-contribution` | -| Archetype | `2 + 4 + 5 + 6` described; docs-only PR | -| Scope overlays | `SCOPE-docs` | +| Field | Value | +| -------------- | -------------------------------------------------- | +| Run ID | `docs-rfc-sdk-client-contribution--rfc` | +| Branch | `docs/rfc-sdk-client-contribution` | +| Archetype | `2 + 4 + 5 + 6` described; docs-only PR | +| Scope overlays | `SCOPE-docs` | +| Draft PR | `https://github.com/rickylabs/netscript/pull/1390` | ## Design -This Design checkpoint is intentionally bootstrap-level. It records the artifact and decision -vocabulary before RFC authoring; exact public types and composition laws will replace the pending -items after research and before `status:plan-eval`. - ### Public Surface -- `rfcs/0000-sdk-client-contributions.md` — proposed public SDK/plugin contract; no product export - is added by this PR. -- Pending RFC types/functions: contribution descriptor, definition helper, client-option generic, - composition/failure types, and plugin declaration carrier. - -### Domain Vocabulary +This PR adds only `rfcs/0000-sdk-client-contributions.md`. The accepted RFC would authorize these +future surfaces: -- **Contribution** — a named, versioned client-construction descriptor supplied explicitly or by a - plugin declaration. -- **Contribution chain** — an immutable ordered tuple whose fold yields one client configuration - and one inferred per-call context. -- **Reserved owner** — the framework or first contribution that exclusively owns a conflicting - field/key. -- **Sensitive value** — credential/header/context data whose diagnostics must retain metadata but - redact value material. +- `@netscript/contracts`: `NetScriptProcedureMeta` and `NetScriptAuthenticationRequirement` at the + root. +- `@netscript/sdk/ports`: upstream-free contribution descriptor/context/cache/error contracts. +- `@netscript/sdk/client` and root: definition helper, errors, context-generic clients and query + types, re-exported for L2/L3 use. +- `@netscript/plugin/config`: optional `sdkClients` module reference group. +- `@netscript/plugin-auth-core/sdk`: constrained bearer contribution factory. -### Ports +No new generic transport/plugin/query middleware envelope is authorized. -- No product port is introduced in this docs PR. The RFC must decide whether the current client-link - seam is sufficient and what transport ownership remains framework-only. - -### Constants +### Domain Vocabulary -- RFC number remains `0000` until maintainer acceptance. -- Contribution contract version and finite error codes remain pending research; the RFC will name - them only if their stability value exceeds their compatibility cost. +- **Contribution** — versioned, named request-header preparer with runtime context declaration. +- **Preparation snapshot** — immutable context/procedure/transport/input passed independently to + each contributor. +- **Header ownership** — exclusive lower-case header reservation; no overwrites. +- **Response-cache effect** — `invariant`, `partitioned`, or `direct-only` safety declaration. +- **Partition** — synchronous, stable, non-secret full-key discriminator visible in cache tools. +- **Transport policy** — SDK-owned discovery/codec/fetch/retry/dedupe/trace/dispatch. + +### Composition Law + +1. A literal tuple derives one per-service context intersection. +2. Construction validates family/major, id, limits, required/optional context declaration, headers, + cache effect, and duplicate ownership. +3. Calls execute contributors sequentially in tuple order with the same snapshot. +4. Contributors never observe accumulated results; valid disjoint patches commute. +5. Tuple order affects only deterministic first-error reporting. +6. Merged contributed headers enter the single native oRPC async header resolver. +7. Transport adds base content type and final client-span trace headers, then dispatches. + +### Context and Query Law + +- Required contributed properties make the request options/context required. +- Context is threaded through direct, server-query, and TanStack paths. +- Context/input/credentials never enter query keys. +- `partitioned` values add an id-sorted suffix to full keys only. +- `direct-only` service keys are absent from generated query/query-utils maps. +- No contribution may author query defaults, callbacks, or arbitrary key fragments. + +### Ports and Boundaries + +- The RFC composes oRPC's existing async `RPCLink.headers` behavior behind NetScript-owned types. +- The internal `ClientLinkPort` is evidence for #451; it is not exposed by this RFC. +- `RPCHandlerConfig.plugins` remains the separate server plugin axis. +- Trace propagation is transport-owned; `traceparent`/`tracestate` are reserved. + +### Security and Failure + +- All contributed header values are sensitive by default. +- Stable diagnostics allow only code/phase/id/path/header-name/service/duration. +- Input, context, values, source messages, and source causes are forbidden; resolver failures are + discarded rather than attached to the exported error. +- Bearer resolution is per call, respects metadata, defaults unmarked routes to `none`, rejects + missing required credentials, and refuses cleartext non-local use absent explicit unsafe choice. +- Contribution failures happen before dispatch and are not server-defined errors. +- Fetch-forbidden, SDK-owned, undeclared, mixed-case, non-string, and CR/LF headers fail. + +### Constants and Budgets + +- RFC number: `0000` until maintainer acceptance. +- Protocol: `netscript.sdk-client`, major `1`. +- Maximum: 16 contributions/service, 8 context keys/contributor, 16 header keys/contributor. +- Id: lower-case `:`, 3–128 ASCII characters. +- Cache partition: 1–64 printable ASCII, explicitly non-secret. + +### Package Placement + +| Concept | Owner | +| ---------------------------------------- | --------------------------------- | +| Metadata vocabulary | `@netscript/contracts` | +| Descriptor/type algebra/runtime composer | `@netscript/sdk` | +| Plugin module reference | `@netscript/plugin/config` | +| Bearer convention | `@netscript/plugin-auth-core/sdk` | +| Auth delivery declaration | thin `plugins/auth` | +| Static import/tuple generation | CLI/scaffold tooling | + +### Rejected Surface + +`fetch`, raw links, client/adapter interceptors, oRPC link/server plugins, serializers, retries, +transport error maps, arbitrary query policy, dependency/priority ordering, runtime auto-discovery, +fluent builders, and global registries. ### Commit Slices -| # | Slice | Gate | Files | -| - | ----- | ---- | ----- | -| 1 | Activate run identity and evidence skeleton | direct artifact/path review + git status | `.llm/runs/docs-rfc-sdk-client-contribution--rfc/*` | -| 2 | Lock re-baselined research and RFC design | source/API citations + type probes + Plan-Gate checklist | `research.md`, `plan.md`, `worklog.md`, `context-pack.md`, `drift.md`, `rfcs/0000-sdk-client-contributions.md` | -| 3 | Prove docs/JSR/GitHub readiness and hand off | applicable docs/RFC gates + live PR metadata reconciliation | RFC, run artifacts, `final-handoff.md`, draft PR body/comments/labels | +| # | Slice | Gate | Files | +| - | -------------------------------------------- | ------------------------------------------------ | --------------------------------------------- | +| 1 | Activate run identity and evidence skeleton | identity/path review + git status | run bootstrap artifacts | +| 2 | Lock research and author the RFC | source/API citations + type proof + formatting | RFC plus research/design artifacts | +| 3 | Prove docs/JSR/GitHub readiness and hand off | docs/RFC/doctrine gates + live PR reconciliation | final artifact updates and `final-handoff.md` | ### Deferred Scope -- Framework implementation and migrations — separate post-acceptance issues/PRs. -- RFC number and decision state beyond Draft — maintainer-owned lifecycle. -- Formal/cross-RFC evaluator execution — root orchestrator owns existing external sessions. +- Framework implementation and migrations: post-acceptance issues/PRs. +- RFC number and lifecycle beyond Draft: maintainer-owned. +- Formal cross-RFC evaluator execution: root orchestrator owns existing Fable/Qwen sessions. +- Custom transport: #451. ### Contributor Path -Read the accepted RFC's terminology and invariants, then follow its staged issue decomposition: -contract/type surface first, composition/runtime second, two first-party consumer proofs third, -generated/scaffold ergonomics and documentation last. +Implement contracts/types first, then runtime composition/cache safety, then auth and locale proofs, +then discovery/generated/docs. Each slice must meet the RFC conformance gates before it can be +considered complete. ## Progress Log -| Time | Slice | Step | Notes | -| --- | --- | --- | --- | -| 2026-08-08 | 1 | bootstrap | Read requested skills, RFC process, harness workflow/gates/evaluator protocols, selected archetypes, doctrine 01–11, relevant debt, and the full carried-in proposal. | -| 2026-08-08 | 1 | identity | Verified exact branch/base, clean tracked tree, daemon launch artifact, native WSL path, explicit-refspec rule, and valid GitHub credential. | +| Date | Slice | Step | Evidence/result | +| ---------- | ----- | ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------- | +| 2026-08-08 | 1 | authority/identity | Read all requested skills, full harness/RFC/doctrine/profile authorities, relevant debt, and full proposal; verified exact base/session/path/auth. | +| 2026-08-08 | 1 | bootstrap | Created mandatory artifacts, committed `158849031bba78025d0ec16c8361628211fbc4ed`, pushed explicit refspec, opened draft PR #1390. | +| 2026-08-08 | 1 | PR metadata | Applied required labels plus sole `status:research`; no milestone; body references #1348 without closing keyword; posted slice S1 comment. | +| 2026-08-08 | 2 | live board | Re-read #1347–#1353 and #1093/#451/#928/#934/#922/#884, including milestone mapping; no mutation. | +| 2026-08-08 | 2 | public API | Used `deno doc` for SDK/service/plugin/contracts and focused source reads for link/query/metadata/auth/telemetry paths. | +| 2026-08-08 | 2 | dependency | `deps:why` proves live oRPC client; stable report says coherent family is behind to 1.15.0 as of research date. | +| 2026-08-08 | 2 | upstream | Verified official oRPC headers/context/metadata docs and Fetch/W3C/RFC/OWASP primary security sources. | +| 2026-08-08 | 2 | type proof | Scratch Deno proof passes required/optional intersection, named conflicts, 16 accepted, 17 rejected. | +| 2026-08-08 | 2 | design correction | Rejected trace as second consumer; chose locale. Added mandatory cache-effect law after finding query context/key erasure. | +| 2026-08-08 | 2 | RFC | Authored and formatted 1,000+ line decision-complete `rfcs/0000-sdk-client-contributions.md`. | +| 2026-08-08 | 2 | JSR baseline | Four package dry-runs OK; structured doc-lint/private-type baselines and existing plugin audit failure recorded. | +| 2026-08-08 | 3 | doctrine | `deno task arch:check` exits 0; warning-only package debt is pre-existing and remains unwaived. | +| 2026-08-08 | 3 | plan gate | Self-audit covers current state/gap, alternatives, exact surface, laws, failures, migration, slices/issues, and gates; no evaluator verdict claimed. | +| 2026-08-08 | 3 | final docs/type | Re-ran exact-shape type proof, six-file format check, 102-document links, docs accuracy, focused RFC links, and diff hygiene; all pass. | ## Decisions -| Decision | Reason | Source | -| --- | --- | --- | -| Treat RFC authorship as Plan & Design, not framework implementation. | The deliverable is the ratifiable plan; no product code is authorized. | `rfcs/README.md`; task brief; harness run loop | -| Use Archetypes 2/4/5/6 plus `SCOPE-docs`. | Those are the current assigned profiles of the implementation surfaces the RFC describes. | doctrine 06/11; harness archetypes | -| Do not launch or repair a session. | The existing thread is proven and the owner forbids a rival; runtime-controller registration absence does not imply daemon failure. | `codex-thread-ids.md`; codex-wsl-remote skill | +| Decision | Reason | Source | +| ------------------------------------------ | -------------------------------------------------------------------------------------- | ------------------------------------------- | +| Treat RFC authorship as Plan & Design. | Deliverable is ratifiable architecture; product code is forbidden. | RFC process, brief, harness run loop | +| Use Archetypes 2/4/5/6 plus `SCOPE-docs`. | Current assigned profiles of described implementation surfaces. | doctrine 06/11, harness profiles | +| Do not launch/repair a session. | Existing thread is proven; owner forbids rival authorship. | `codex-thread-ids.md`, WSL skill | +| Narrow to header preparation. | Existing native async seam covers both consumers; other fields have different owners. | SDK source, oRPC declarations/docs, A11/A14 | +| Make valid composition order-independent. | Doctrine forbids semantic plugin-order dependence; exclusive keys make it enforceable. | doctrine extension-axis law | +| Add mandatory cache effect. | Context/header variants can otherwise collide in current query keys. | query source and upstream query types | +| Keep trace transport-owned. | Client span is created at fetch dispatch; earlier trace header is wrong/overwritten. | `http-client-link.ts`, W3C Trace Context | +| Put bearer factory in auth core. | Convention-bearing primitive belongs in core; plugin stays thin. | doctrine 11 | +| Keep errors separate from contract errors. | Preparation precedes any server response. | failure taxonomy, #1350 boundary | ## Drift -| Drift | Severity | Logged in drift.md | -| --- | --- | --- | -| Runtime controller did not match the launch-generated active thread identity. | minor | yes | +| Drift | Severity | Logged in drift.md | +| ------------------------------------------------------------------------------ | ------------------------ | ------------------ | +| Runtime controller did not match the launch-generated active thread. | minor | yes | +| Owner-directed external review route differs from default evaluator lane. | significant, authorized | yes | +| Proposal's trace second consumer conflicts with current client-span injection. | significant design drift | yes | +| Proposal omitted cache identity risk of typed auth/locale context. | significant design drift | yes | +| Current package doc-lint/JSR baselines contain pre-existing findings. | baseline | yes | ## Gate Results -Gate execution begins after RFC authoring; bootstrap evidence is recorded above. +| Gate | Command | Result | +| --------------------- | ---------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | +| RFC format | `deno fmt --check rfcs/0000-sdk-client-contributions.md` | PASS after format | +| Focused RFC links | link checker with `--root rfcs/0000-sdk-client-contributions.md` | PASS, 0 broken links/anchors | +| Repository docs links | `deno task docs:links` | PASS, 102 docs, 0 broken links/anchors | +| Docs accuracy | `deno task docs:accuracy` | PASS | +| Type proof | `deno check --config .llm/tmp/deno.json .llm/tmp/sdk-client-contribution-probe.ts` | PASS | +| Package audit | four `audit-jsr-package.ts --text` runs | contracts/sdk/auth-core exit 0; plugin exit 1 on pre-existing 4 module-tag + cardinality findings; all dry-runs OK | +| Structured doc lint | four `run-deno-doc-lint.ts` runs | baseline private refs: contracts 9, SDK 3, plugin 15, auth-core 4; report command exits 0 | +| Doctrine | `deno task arch:check` | PASS, exit 0; existing warning-only package debt recorded and not waived | +| Plan Gate self-audit | checklist against `plan-gate.md` and RFC required sections | PASS for evaluator entry; not a PLAN-EVAL verdict | +| Diff hygiene | `git diff --check` | PASS | + +Live PR reconciliation remains pending rather than implied complete. ## Handoff Notes -- External reviewers should challenge whether each proposed field has a named extension axis and - whether both first-party proofs exercise it. +External reviewers should attack: +1. whether the cache-effect law fully closes cross-principal/context query reuse; +2. whether any rejected transport field is actually required for the two consumers; +3. whether context declaration/static/runtime diagnostics are implementable within the stated + inference budget; +4. whether redaction permits any indirect token/partition leakage or source-error reappearance; and +5. whether plugin availability versus explicit activation is sufficiently concrete for #1093 and + generators. diff --git a/rfcs/0000-sdk-client-contributions.md b/rfcs/0000-sdk-client-contributions.md new file mode 100644 index 0000000000..60509c9104 --- /dev/null +++ b/rfcs/0000-sdk-client-contributions.md @@ -0,0 +1,1074 @@ +--- +rfc: 0000 +title: Typed SDK client contributions +status: Draft +authors: ['@rickylabs'] +created: 2026-08-08 +tracking-issue: https://github.com/rickylabs/netscript/issues/1348 +target-milestone: 0.0.7 +--- + +# Typed SDK client contributions + +## Summary + +This RFC adds one deliberately narrow extension axis to `@netscript/sdk`: a versioned, named, typed +contribution may prepare request headers from immutable per-call context before the SDK's HTTP link +dispatches a service call. A literal contribution tuple determines the client context type, reserves +header and context ownership, and fails loudly on duplicates. The SDK keeps ownership of discovery, +serialization, retry, deduplication, tracing, fetch, and transport. Query helpers receive the same +context only when each contribution proves that its response cache is invariant or supplies a +synchronous, non-secret partition; otherwise the contributed client is direct-call-only. + +The design composes oRPC's existing async `RPCLink.headers` and client-context mechanisms. It does +not expose upstream oRPC types or create a second middleware framework. Bearer credentials in +`@netscript/plugin-auth-core` are the first dogfood consumer. A locale contribution, which owns +`accept-language`, is the required non-auth proof. Trace propagation remains transport-owned because +the final `traceparent` must describe the SDK's client span, not an earlier header callback. + +## Motivation + +### Current baseline + +The starting proposal described a single `SdkClientContribution` envelope containing request +context, headers, oRPC interceptors and plugins, `fetch`, links, errors, metadata, and query policy. +Current `main` does not justify that width: + +| Current fact | Consequence | +| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| [`CreateServiceClientOptions`](../packages/sdk/src/ports/service-client.ts) is a closed nine-field record. `port` and `timeout` are accepted but not consumed. | Apps cannot add a bearer or locale header. Silent reserved options must not become precedent for more no-op fields. | +| [`createHttpClientLink`](../packages/sdk/src/client/http-client-link.ts) already owns `Content-Type`, retry, GET deduplication, a traced `fetch`, cache/signal forwarding, and trace injection. | Those mechanisms are transport policy, not independently composable request contributions. | +| [`ServiceClientContext`](../packages/sdk/src/ports/service-client.ts) is fixed, while [`ServiceClientMethod`](../packages/sdk/src/ports/service-client.ts) does not carry a context generic. | A credential source cannot add required per-call context without a framework type change. | +| [`defineServices`](../packages/sdk/src/presets/define-services.ts), [`QueryFactory`](../packages/sdk/src/ports/query-factory.ts), and [`ServiceQueryUtils`](../packages/sdk/src/ports/service-query-utils.ts) erase client context. | Merely fixing direct calls would leave generated/query paths unsound or unusable. | +| [`ClientLinkPort`](../packages/sdk/src/ports/client-link-factory.ts) is already a package-owned structural link, but it is internal. | A future transport escape hatch should unhide this seam, not put raw oRPC links or `fetch` callbacks in a contribution. | +| [`RPCHandlerConfig.plugins`](../packages/service/src/primitives/handlers.ts) already accepts server handler plugins. | Server plugin reachability is a service-preset problem, not a client-contribution field. | +| [`PluginContributions`](../packages/plugin/src/config/domain/plugin-contributions.ts) has no SDK-client group and its doctor check is a closed auth literal. | Plugin discovery needs a generic module-reference axis; core must not hardcode each contributor. | +| [`baseContract`](../packages/contracts/src/application/contract-primitives.ts) does not initialize typed metadata and is annotated as `ReturnType`. | Procedure metadata and the existing error-map erasure need repair, but client preparation errors must not masquerade as server contract errors. | +| The lock resolves the oRPC family to 1.14.6, while the repository's stable-channel tool reported 1.15.0 on 2026-08-08. | The implementation must re-run the stable check and move the family coherently; this RFC must depend on public behavior rather than copied private upstream types. | + +The repository already contains the needed mechanism. In oRPC 1.14.6, `RPCLink` accepts an async +header resolver whose arguments include client options, procedure path, and input. oRPC's client +context also makes a non-empty context required at call sites, and TanStack Query utilities already +thread that context. The official [RPCLink documentation](https://orpc.dev/docs/client/rpc-link) +shows the same header/context path. NetScript currently hides those capabilities behind a fixed +context and a hardcoded callback. + +### User problem + +An application should be able to say, once, that a service client carries a bearer credential and a +locale, then receive all of these properties end to end: + +- direct calls require the inferred context; +- `defineServices()` preserves the same context in generated clients and safe query helpers; +- credential and locale resolution happen for every call, so rotation and request isolation work; +- two contributors cannot silently overwrite each other's headers or context; +- a failed contribution prevents network dispatch and produces a stable, redacted diagnostic; +- installing a third-party plugin does not require another switch statement in core; and +- omitting contributions is exactly today's behavior. + +Without a ratified seam, each plugin must patch the SDK link, create a parallel client, capture a +process-global token, or ask core for another hardcoded option. All four outcomes weaken generated +ergonomics and type safety. + +### Goals + +This RFC MUST: + +1. provide a package-owned, versioned descriptor for request-header preparation; +2. infer per-call context from a literal tuple and diagnose static conflicts; +3. repeat all validation at runtime for JavaScript, widened arrays, and plugin boundaries; +4. define deterministic composition without allowing semantic plugin-order dependencies; +5. preserve auth, locale, and arbitrary input/context secrecy in errors and telemetry; +6. keep response caches partitioned when a contributed header can change representation; +7. make contributions statically discoverable but explicitly selected; and +8. retain SDK ownership of the HTTP transport and its observability invariants. + +### Non-goals + +This RFC does not: + +- expose `fetch`, oRPC interceptors, adapter interceptors, link plugins, server plugins, + serializers, or query-default callbacks through the contribution descriptor; +- define credential refresh/replay after a `401`; +- make client metadata enforce server authorization; +- expose a custom transport option (issue [#451](https://github.com/rickylabs/netscript/issues/451) + owns that independent decision); +- redesign the two existing query-key algebras beyond adding a safe partition suffix; +- fix the `baseContract` error-map erasure tracked by + [#1350](https://github.com/rickylabs/netscript/issues/1350); or +- automatically attach every installed contribution to every service. + +## Terminology + +- **Contribution**: a named, versioned descriptor that owns context keys and possible request header + names and prepares a header patch for one call. +- **Contribution tuple**: the literal `readonly` tuple explicitly attached to a service client. +- **Preparation snapshot**: the immutable context, procedure descriptor, input, and transport + descriptor passed independently to every contribution. +- **Header ownership**: the exclusive right to emit one lower-case request header name. +- **Response-cache effect**: the contributor's declaration that its header is response-invariant, + partitionable, or unsafe for generated query helpers. +- **Partition**: a synchronous, non-secret discriminator added to a full query key. It is not a + credential and is intentionally visible in cache tools. +- **Transport policy**: discovery, URL/method selection, codec, retry, dedupe, tracing, `fetch`, + streaming, and dispatch. The SDK owns it for `createServiceClient()`. + +## Guide-level explanation + +### A non-auth contribution + +Contribution authors use a curried helper. The generic names the context added by the contribution; +the literal fields remain available to the composition algebra. + +```ts +import { defineSdkClientContribution } from '@netscript/sdk/client'; + +export const localeContribution = defineSdkClientContribution<{ locale?: string }>()({ + protocol: { family: 'netscript.sdk-client', major: 1 }, + id: 'app:locale', + context: { locale: 'optional' }, + headerKeys: ['accept-language'], + responseCache: { + mode: 'partitioned', + partition: ({ context }) => context.locale ?? 'default', + }, + prepare: ({ context }) => ({ + headers: context.locale ? { 'accept-language': context.locale } : {}, + }), +}); +``` + +The `context` declaration and `headerKeys` are runtime evidence, not duplicated documentation. The +helper checks that every TypeScript context key is declared with the correct required/optional mode. +Emitted headers must be a subset of `headerKeys`. The locale is a cache partition because it can +change the representation returned for identical procedure input. + +### Auth as the first dogfood consumer + +`@netscript/plugin-auth-core/sdk` supplies a universal bearer factory. The thin `plugins/auth` +package only declares and delivers that module. + +```ts +import { createBearerSdkClientContribution } from '@netscript/plugin-auth-core/sdk'; + +const bearer = createBearerSdkClientContribution<{ + auth: { + getAccessToken(): Promise; + cachePartition: string; + }; +}>({ + context: { auth: 'required' }, + resolveCredential: ({ context }) => context.auth.getAccessToken(), + responseCache: { + mode: 'partitioned', + partition: ({ context }) => context.auth.cachePartition, + }, +}); +``` + +`cachePartition` is a random session/principal epoch or another non-secret identifier. It MUST NOT +be the access token, refresh token, session id, email address, or a reversible encoding of one. If +an auth integration cannot provide a safe synchronous partition, its factory returns a `direct-only` +contribution and generated query helpers are not exposed for that service. + +Procedure metadata tells the auth contribution whether a credential is appropriate: + +```ts +import { baseContract } from '@netscript/contracts'; +import { z } from 'zod'; + +export const accountContract = { + status: baseContract + .meta({ access: { authentication: 'none' } }) + .output(z.object({ ok: z.boolean() })), + profile: baseContract + .meta({ access: { authentication: 'required' } }) + .output(z.object({ displayName: z.string() })), +}; +``` + +For `none`, the bearer contribution emits no credential. For `optional`, it emits one when +available. For `required`, absence is a preparation failure and no request is sent. Unmarked +procedures default to `none` in the first-party bearer factory so installing auth cannot start +leaking credentials to every existing procedure. An application may choose a different explicit +`unmarked` policy when constructing the factory. + +Metadata guides a client contribution; it does not prove that the server enforces the same policy. +Server authentication/authorization remains mandatory. + +### Direct client usage + +```ts +import { createServiceClient } from '@netscript/sdk/client'; + +const accounts = createServiceClient({ + contract: accountContract, + serviceName: 'accounts', + contributions: [bearer, localeContribution] as const, +}); + +const profile = await accounts.profile({}, { + context: { + auth: { + getAccessToken: () => session.accessToken(), + cachePartition: session.cacheEpoch, + }, + locale: 'de-CH', + }, +}); +``` + +The second argument is required because the composed context contains required `auth`. Removing the +auth contribution removes that requirement. Renaming `auth` or passing a tuple with another owner of +`authorization`, `auth`, or the same contribution id is a type error for literal tuples and a +construction error at unknown boundaries. + +### `defineServices`, query factories, and TanStack Query + +```ts +import { defineServices } from '@netscript/sdk'; + +const services = defineServices({ + accounts: { + contract: accountContract, + contributions: [bearer, localeContribution] as const, + }, +}); + +const context = { + auth: { + getAccessToken: () => session.accessToken(), + cachePartition: session.cacheEpoch, + }, + locale: 'de-CH', +}; + +await services.clients.accounts.profile({}, { context }); +await services.queries.accounts.profile({}, { context }); + +const query = services.queryUtils.accounts.profile.queryOptions({ + input: {}, + context, +}); +``` + +Both full query keys receive this canonical suffix, sorted by contribution id: + +```ts +[ + '$netscript.sdk-context', + ['@netscript/plugin-auth:bearer', session.cacheEpoch], + ['app:locale', 'de-CH'], +]; +``` + +The context object and credential are never put in the key. Existing prefix invalidation continues +to work because the suffix is added only to full keys. With no contributions, or only +response-invariant contributions, key shapes are unchanged. + +A `direct-only` contribution remains valid with `services.clients.accounts`, but `accounts` is +omitted from the mapped `queries` and `queryUtils` results. The omission is both compile-time and +runtime; it is not a property containing `undefined`. + +### Async and server-side sources + +`prepare` and `resolveCredential` may be async and are invoked once for every transport attempt that +represents a new logical call. They are never invoked at module import or client construction. An +application may close over a concurrency-safe rotating credential source: + +```ts +const bearer = createBearerSdkClientContribution({ + context: {}, + resolveCredential: () => credentialStore.current(), + responseCache: { mode: 'direct-only' }, +}); +``` + +Environment-reading convenience factories, if shipped, live under explicit `.../sdk/server` or +`.../sdk/browser` exports. Universal modules do not read `Deno.env`, `window`, local storage, or +cookies. The framework does not guess the runtime from globals. + +## Reference-level explanation + +### Architecture and ownership + +This RFC spans four existing archetypes and no new package: + +| Package/surface | Archetype | Responsibility | +| -------------------------------------------------- | ----------------------- | ------------------------------------------------------------------------------------------- | +| `@netscript/contracts` | Public DSL/builder | Own the cross-runtime procedure metadata vocabulary. | +| `@netscript/sdk/ports` and `@netscript/sdk/client` | Public DSL/builder | Own upstream-free descriptor types, type algebra, preparation errors, and the HTTP adapter. | +| `@netscript/sdk` | Public preset | Preserve tuples through `defineServices()` and expose one-call ergonomics. | +| `@netscript/plugin/config` | Plugin protocol/config | Carry static module references without importing SDK runtime types. | +| `@netscript/plugin-auth-core/sdk` | Plugin core/integration | Own the convention-bearing bearer contribution and security policy. | +| `plugins/auth` | Thin plugin delivery | Declare the module reference and generated/scaffold wiring only. | +| CLI generators | Tooling | Generate explicit imports and literal tuples; validate plugin references. | + +This follows the doctrine's extension-axis law: a cross-package extension is named, registered, +deterministic, and duplicate-rejecting. It also follows the public-surface law: NetScript owns the +types and does not re-export `RPCLinkOptions`, `ClientOptions`, `StandardHeaders`, upstream plugin +types, or interceptor types. + +### Procedure metadata + +`@netscript/contracts` adds the following root exports and initializes `baseContract` with them: + +```ts +export type NetScriptAuthenticationRequirement = + | 'none' + | 'optional' + | 'required'; + +export interface NetScriptProcedureMeta { + readonly access?: { + readonly authentication?: NetScriptAuthenticationRequirement; + }; +} + +const contractWithMeta = oc.$meta({}); +export const baseContract = contractWithMeta.errors(commonErrorMap); +``` + +The implementation MUST use an explicit publishable annotation that preserves both the concrete +common error map and `NetScriptProcedureMeta`; it MUST NOT retain the erasing +`ReturnType` annotation. The exact error-map repair belongs to #1350, but the +metadata and error work must land coherently so one does not re-erase the other. + +`ContractProcedureMetadata` in `@netscript/sdk/ports` gains a package-owned `meta` member and the +SDK normalizes missing metadata to `{}`. This mirrors the public `procedure['~orpc'].meta` field +documented by [oRPC metadata](https://orpc.dev/docs/metadata) without exporting an upstream type. + +### Public contribution contract + +The normative shape is: + +```ts +export type SdkClientContributionId = `${string}:${string}`; + +export interface SdkClientContributionProtocol { + readonly family: 'netscript.sdk-client'; + readonly major: 1; +} + +export interface SdkClientProcedureDescriptor { + readonly path: readonly string[]; + readonly meta: Readonly; +} + +export interface SdkClientTransportDescriptor { + readonly kind: 'http'; + readonly origin: URL; + readonly rpcPath: string; + readonly secure: boolean; +} + +export interface SdkClientPrepareOptions { + readonly context: Readonly; + readonly procedure: SdkClientProcedureDescriptor; + readonly transport: SdkClientTransportDescriptor; + readonly input: unknown; +} + +export interface SdkClientRequestPatch { + readonly headers?: Readonly>; +} + +export type SdkClientContextDeclaration = { + readonly [K in Extract]-?: Record extends Pick + ? 'optional' + : 'required'; +}; + +export interface SdkClientCachePartitionOptions { + readonly context: Readonly; + readonly procedure: SdkClientProcedureDescriptor; +} + +export type SdkClientResponseCache = + | { readonly mode: 'invariant' } + | { + readonly mode: 'partitioned'; + readonly partition: ( + options: SdkClientCachePartitionOptions, + ) => string; + } + | { readonly mode: 'direct-only' }; + +export interface SdkClientContribution< + TId extends SdkClientContributionId = SdkClientContributionId, + TContext extends object = Record, + TContextDeclaration extends SdkClientContextDeclaration = SdkClientContextDeclaration< + TContext + >, + THeaderKeys extends readonly string[] = readonly string[], +> { + readonly protocol: SdkClientContributionProtocol; + readonly id: TId; + readonly context: TContextDeclaration; + readonly headerKeys: THeaderKeys; + readonly responseCache: SdkClientResponseCache; + readonly prepare: ( + options: SdkClientPrepareOptions, + ) => SdkClientRequestPatch | PromiseLike; +} +``` + +`defineSdkClientContribution()(descriptor)` preserves `id`, the context declaration, +header keys, and cache mode as literals. Its parameter applies these static checks: + +- `context` contains every and only string key of `TContext`, and each value agrees with whether + that TypeScript property is required or optional; +- header names are lower-case string literals; +- ids contain 3–128 ASCII characters, match `^[a-z0-9@][a-z0-9@._/-]*:[a-z0-9][a-z0-9._-]*$`, and do + not use the reserved `@netscript/internal:` owner; and +- one descriptor declares at most eight context keys and sixteen header keys. + +The descriptor contains no generic `TypeMarker`, mutable builder, dependency list, priority, +environment flag, upstream callback, or arbitrary metadata bag. Major version 1 is intentionally +closed. + +The first-party auth factory has this constrained surface: + +```ts +export interface CreateBearerSdkClientContributionOptions< + TContext extends object, +> { + readonly context: SdkClientContextDeclaration; + readonly resolveCredential: ( + options: SdkClientPrepareOptions, + ) => string | undefined | PromiseLike; + readonly responseCache: SdkClientResponseCache; + readonly unmarked?: NetScriptAuthenticationRequirement; + readonly allowInsecureTransport?: boolean; +} + +export function createBearerSdkClientContribution>( + options: CreateBearerSdkClientContributionOptions, +): SdkClientContribution< + '@netscript/plugin-auth:bearer', + TContext, + SdkClientContextDeclaration, + readonly ['authorization'] +>; +``` + +`unmarked` defaults to `none`; `allowInsecureTransport` defaults to `false`. The resolver is not +called for `none`, is optional for `optional`, and must return a value for `required`. The factory +adds the `Bearer` scheme, so callers return only the token and cannot inconsistently author the +header. The descriptor id, header ownership, protocol, and preparation implementation are fixed by +auth core rather than caller-configurable. + +### Tuple type algebra + +The SDK exports `SdkClientContributionContext` for tooling and uses it internally. +It recursively intersects contributor contexts while tracking seen ids, context keys, and header +keys. A conflict produces a named structural diagnostic such as: + +```ts +{ + readonly __netscriptContributionConflict: 'header:authorization'; +} +``` + +The `contributions` option is intersected with `ValidateSdkClientContributions`, so that marker +appears at the tuple boundary rather than turning one context property into an unexplained `never`. +The type recursion stops at sixteen contributions per service. A seventeenth literal is a named +`limit:more-than-16` diagnostic. Widened arrays retain correct context unions but receive full +conflict validation only at runtime. + +The client surface becomes context-generic with compatibility defaults: + +```ts +export type ServiceRequestRest = RequiredKeys extends never + ? [options?: { readonly context?: TContext }] + : [options: { readonly context: TContext }]; + +export type ServiceClientMethod = ( + input: TInput, + ...request: ServiceRequestRest +) => Promise; + +export type ServiceClient< + TContract extends ContractLike, + TContext extends object = ServiceClientContext, +> = ServiceClientShape & ServiceClientContract; + +export interface CreateServiceClientOptions< + TContract extends ContractLike, + TContributions extends readonly AnySdkClientContribution[] = readonly [], +> { + // Existing fields remain. + readonly contract: TContract; + readonly serviceName: string; + readonly contributions?: + & TContributions + & ValidateSdkClientContributions; +} +``` + +`createServiceClient()` returns +`ServiceClient>`. All +existing single-generic references continue to mean the current `ServiceClientContext`. + +### Query and generated type propagation + +`DefineServiceConfig` gains the contribution tuple generic. Its mapped results infer one composite +context per service rather than widening the entire services map. + +The same context generic is threaded through: + +- `FactoryConfig`, `QueryFactory`, `ActionMethod`, and the internal `invokeClientProcedure`; +- `ServiceQueryUtils`, every procedure query/infinite/mutation option, and `.call`; +- `createQueryFactory`, `createServiceQueryUtils`, and `createQueryFactories`; and +- `DefinedServiceClients`, `DefinedServiceQueries`, and `DefinedServiceQueryUtils`. + +Cache policy options and request context remain separate types. Context MUST NOT be accepted as an +untyped field on `QueryParams` and MUST NOT be stored in default service options. Per-call query +execution options compose `QueryParams` with the same conditional context requirement used by the +client. + +Every contribution has one mandatory response-cache mode: + +- `invariant`: the header cannot affect response selection or representation. No key suffix is added + for this contribution. +- `partitioned`: the synchronous resolver returns a stable, non-secret ASCII value of 1–64 + characters. The pair `[contributionId, value]` is added to full server and TanStack keys. +- `direct-only`: the SDK cannot safely cache calls using this contribution. `defineServices()` omits + that service key from both `queries` and `queryUtils`. + +Partition resolvers are synchronous because TanStack option/key factories are synchronous. They +receive context and the package-owned procedure descriptor, but no transport because service +discovery may be asynchronous and no input because input already participates in full keys. They +MUST NOT perform I/O, read a credential, throw secret-bearing messages, or return an unstable value. +All partition pairs are sorted by contribution id, making key identity independent of tuple order. +Duplicate ids are already invalid. + +The cache suffix is appended only to full keys. Resource/procedure prefixes and existing +invalidation helpers remain unchanged. A conformance test MUST prove that two auth partitions with +identical input cannot observe each other's server or TanStack cached data. + +This narrow cache-effect declaration is not a query contribution. It cannot set stale times, retry, +invalidation callbacks, query functions, or arbitrary key fragments. + +### Composition and ordering law + +Construction performs these steps in tuple order: + +1. validate the protocol family and major, id grammar, tuple/key limits, and plain-object shape; +2. canonicalize declared header names to lower case and reject non-canonical input; +3. reserve framework and Fetch-owned headers; +4. reject duplicate ids, context keys, and header keys; and +5. validate query compatibility and generated surface selection. + +At call time: + +1. resolve the service origin and procedure node; +2. create one read-only preparation snapshot; +3. invoke contributors sequentially in tuple order with that same snapshot; +4. after each await, validate that the patch is a plain record, every header was declared, values + are valid strings without CR/LF, and the call has not been aborted; +5. merge the disjoint patches into a new record; +6. pass that record to the single native oRPC header resolver; and +7. let the SDK transport encode, trace, retry/dedupe, fetch, and decode the call. + +Contributions never see accumulated headers or another contribution's result. Valid contributions +therefore commute: tuple order cannot change a successful request. Order determines only which +invalid descriptor or failing preparation is reported first. A plugin MUST NOT rely on discovery or +tuple order for semantics, and version 1 has no `before`, `after`, `requires`, `priority`, or +numeric `order` field. + +Sequential preparation is chosen over `Promise.all` to make the first failure deterministic and to +avoid leaving multiple secret resolvers running after a known failure. Contributors still must be +independent. + +### Header ownership and reserved names + +`headerKeys` reserves possible output, not mandatory output. A contributor may omit a declared +header for a particular procedure but may never emit an undeclared one. + +The following are unavailable to contributions: + +- SDK-owned `content-type`, `traceparent`, and `tracestate`; +- every + [Fetch forbidden request-header name](https://fetch.spec.whatwg.org/#forbidden-request-header), + including `cookie`, `content-length`, `host`, `origin`, and transport-hop fields; +- names beginning `proxy-` or `sec-`; and +- `set-cookie`, which is a response field. + +The implementation keeps an audited lower-case snapshot of the Fetch list and tests the prefix +rules. `authorization`, `accept-language`, and `idempotency-key` are permitted. Browser CORS +preflight remains an application/deployment concern and must be documented by any plugin emitting a +non-safelisted header. + +There is no last-writer-wins mode, no opt-in overwrite, and no deletion syntax. Framework base +headers are not visible to contributors. The transport adds `Content-Type` and the client span's +trace fields after contribution validation. + +### Async context, retries, and cancellation + +Preparation runs once per logical client call, before oRPC retry machinery. Retries reuse the +prepared result for that call. This avoids fetching a different credential or locale halfway through +one retry sequence. Credential refresh after a `401` requires a future explicit replay policy; an +interceptor hidden in an auth contribution would make side-effect replay unsafe. + +If the call signal is already aborted, no contributor runs. If it aborts during an async resolver, +the SDK stops awaiting, does not dispatch, and rejects with the platform abort reason. A resolver +receives the signal through `ServiceClientContext` and SHOULD stop its own work. The SDK cannot +cancel arbitrary promise side effects. + +The snapshot is shallowly read-only at the type level and its top-level records are frozen in +development/test builds. The SDK does not deep-clone input or context, because that would destroy +functions, signals, streams, and identity. Contributors MUST treat nested values as borrowed and +must not mutate them. + +### Transport ownership and oRPC alignment + +Version 1 contributes only the existing oRPC `RPCLink.headers` capability. The adapter supplies one +composed async resolver. This is the thinnest mapping to an upstream public seam and preserves +NetScript's ability to replace oRPC without changing public contribution types. + +The SDK remains the sole owner of: + +- service discovery, origin and RPC path; +- HTTP method inference and codec/serialization; +- `fetch`, cookies/credentials mode, redirect behavior, and TLS policy; +- retry, deduplication, timeout/cancellation, and streaming recovery; +- client spans and final trace injection; and +- decoding and server-defined error transport. + +Accordingly the descriptor has no `fetch`, `link`, `plugins`, `interceptors`, `clientInterceptors`, +`adapterInterceptors`, serializer, retry, or error-map fields. The transport consolidation issue +[#1351](https://github.com/rickylabs/netscript/issues/1351) may refactor those internals and update +oRPC, but it MUST keep one SDK-owned policy path. + +Issue #451 may separately expose a custom transport. If accepted, it MUST adapt the existing +package-owned `ClientLinkPort`, declare whether it accepts prepared request headers, and reject a +header contribution when the selected link lacks that capability. It MUST NOT accept a raw oRPC link +type through this descriptor. + +Trace propagation is not a contribution. The current transport creates a CLIENT span inside its +`fetch` wrapper and injects that span into the final request. A preceding trace-header contribution +would be overwritten or would describe the wrong parent. `propagateTraceContext` and +`ServiceClientContext.traceHeaders` remain compatibility inputs to transport policy; the transport +reserves `traceparent` and `tracestate`. The W3C +[Trace Context recommendation](https://www.w3.org/TR/trace-context/) also requires careful mutation +and calls out correlation/privacy risk. + +### Error and failure model + +The SDK exports one package-owned error and its redacted diagnostic shape: + +```ts +export type SdkClientContributionErrorCode = + | 'SDK_CONTRIBUTION_INVALID' + | 'SDK_CONTRIBUTION_VERSION' + | 'SDK_CONTRIBUTION_CONFLICT' + | 'SDK_CONTRIBUTION_LIMIT' + | 'SDK_CONTRIBUTION_RUNTIME' + | 'SDK_CONTEXT_MISSING' + | 'SDK_HEADER_INVALID' + | 'SDK_CACHE_PARTITION_INVALID' + | 'SDK_PREPARATION_FAILED'; + +export interface SdkClientContributionDiagnostic { + readonly code: SdkClientContributionErrorCode; + readonly phase: 'construction' | 'partition' | 'preparation'; + readonly contributionId?: SdkClientContributionId; + readonly procedurePath?: string; + readonly headerName?: string; +} + +export class SdkClientContributionError extends Error { + readonly code: SdkClientContributionErrorCode; + readonly phase: 'construction' | 'partition' | 'preparation'; + readonly contributionId?: SdkClientContributionId; + readonly procedurePath?: string; + readonly headerName?: string; + toJSON(): SdkClientContributionDiagnostic; +} +``` + +Construction and request failures use the same stable class but distinct `phase`. `message` is +framework-authored and contains only safe identifiers. A rejected resolver's original error is not +attached as `cause`, copied into the message, logged, or emitted to telemetry. Contribution authors +that need internal diagnostics must observe and sanitize their own source failure before rejecting. + +| Failure | Earliest phase | Required behavior | +| --------------------------------------------------------- | ----------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | +| Bad protocol family/major, id, shape, or limit | compile when literal; construction always | Throw before a client is returned. | +| Duplicate id/context/header ownership | compile when literal; construction always | Name the conflict and both contributor ids; never choose a winner. | +| Missing required TypeScript context | compile | Make the request options/context required. | +| Missing context through JS/`unknown` | preparation | Throw `SDK_CONTEXT_MISSING`; do not dispatch. | +| Resolver rejects or throws | preparation | Throw stable `SDK_PREPARATION_FAILED`; discard the source error from the public failure. | +| Undeclared, forbidden, non-string, or CR/LF header | preparation | Throw `SDK_HEADER_INVALID`; do not dispatch. | +| Invalid partition syntax | partition | Throw before cache access. First-party tests separately reject known secret sources; arbitrary secrets cannot be detected reliably at runtime. | +| Abort before/during preparation | preparation | Propagate abort reason; do not dispatch. | +| Discovery, codec, network, retry, or server-defined error | transport | Preserve the existing SDK/oRPC error path; do not relabel it as a contribution failure. | + +Contribution errors are local construction/transport-preparation errors. They are not +`defined: true`, are not merged into contract error unions, and are not accepted by `.errors(...)`. +#1350 repairs server-defined error inference independently. + +### Security, privacy, and redaction + +All contribution-produced header values are classified sensitive by default, not only +`authorization`. The SDK and first-party plugins MUST NOT record: + +- header values or a serialized `Headers` object; +- input, context, credential resolver results, or cache partition source data; +- source error messages/causes from `prepare`; or +- URLs containing userinfo or query/fragment material. + +Allowed diagnostics are the stable code, phase, contribution id, procedure path, declared header +name, service name, and duration. Debug mode does not relax this list. The +[OWASP logging guidance](https://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html#data-to-exclude) +specifically excludes access tokens and session identifiers from direct logs. + +Partition values are intentionally visible in query keys and developer tools. The API docs and +runtime diagnostics MUST say this. First-party auth accepts only an explicitly supplied non-secret +partition and never derives one from a bearer token. + +The bearer factory additionally MUST: + +- emit `authorization` only for allowed metadata policy; +- reject a missing credential for `required` before dispatch; +- avoid module-scope credential reads; +- refuse cleartext non-local origins unless the caller makes an explicit unsafe transport choice; +- never attach a credential after a cross-origin redirect; transport owns redirect policy; and +- document CORS/preflight and cookie-auth limitations. + +For this check, `secure` means an `https:` origin. The only cleartext development exceptions are +`localhost`, a `.localhost` subdomain, IPv4 loopback (`127.0.0.0/8`), and IPv6 loopback (`::1`), +compared after URL hostname parsing. Other `http:` origins require `allowInsecureTransport: true`; +the resulting risk must be explicit in application configuration and diagnostics without exposing a +credential. + +HTTP authentication depends on the confidential transport underneath it; see +[RFC 9110 section 17.16.1](https://www.rfc-editor.org/rfc/rfc9110.html#section-17.16.1). Cookie +authentication is not implemented by setting a `cookie` header. Browser cookie credentials and +`fetch`'s `credentials` mode remain transport/topology decisions. + +### Plugin discovery and generated clients + +`@netscript/plugin/config` adds an upstream-free reference: + +```ts +export interface SdkClientContributionReference { + readonly protocol: { + readonly family: 'netscript.sdk-client'; + readonly major: 1; + }; + readonly id: `${string}:${string}`; + readonly module: string; + readonly export: string; + readonly targets: readonly ('browser' | 'server')[]; +} + +export interface PluginContributions { + readonly sdkClients?: readonly SdkClientContributionReference[]; + // Existing groups remain. +} +``` + +The reference identifies an available named export. It does not contain a serialized function and +does not automatically activate it. The generic discovery work in +[#1093](https://github.com/rickylabs/netscript/issues/1093) must collect these references without +official-plugin switches, reject duplicate ids or mismatched imported descriptors, and expose them +to generators. + +Generated code uses static imports and explicit literal tuples: + +```ts +import { bearerContribution } from '@netscript/plugin-auth-core/sdk'; +import { localeContribution } from './sdk/locale.ts'; + +export const services = defineServices({ + accounts: { + contract: accountContract, + contributions: [bearerContribution, localeContribution] as const, + }, +}); +``` + +No runtime scans installed packages, filesystem manifests, globals, or environment variables. +Installation makes a contribution available; a scaffold/app selection attaches it to a named +service. Generators preserve `as const`, use only public package exports, filter references by +target, and fail generation rather than silently omitting an incompatible target. + +The `(family, major)` protocol vocabulary aligns with the frontend contribution negotiation in +[#928](https://github.com/rickylabs/netscript/issues/928), but the payloads are intentionally +different. UI contributions and SDK request contributions are separate named extension axes, not one +universal envelope. Gateway work in [#934](https://github.com/rickylabs/netscript/issues/934) may +consume the same `NetScriptProcedureMeta.access` vocabulary without depending on SDK contributor +types. + +### Inference and runtime budgets + +Version 1 sets explicit budgets: + +- at most 16 contributions per service; +- at most 8 context keys and 16 header keys per contribution; +- ids at most 128 ASCII characters; +- partition strings at most 64 printable ASCII characters; and +- sequential preparation with at most one outstanding contributor promise. + +The limit applies per service, so a large `defineServices` map does not create one repository-wide +intersection. The implementation uses tail recursion over literal tuples and named conflict markers. +A scratch Deno type probe on the RFC branch checked two composed contexts, required call arguments, +a duplicate-context diagnostic, an accepted 16-element tuple, and a rejected 17-element tuple in +0.67 seconds with a 225,508 KiB maximum RSS on the authoring host. That timing is evidence, not a +portable CI threshold. + +Raising a budget without changing semantics is a backward-compatible implementation decision after +type-performance evidence. Removing a limit or accepting a previously invalid descriptor does not +change protocol major 1. Lowering a limit is breaking. + +### Compatibility and migration + +This is additive for consumers that do not opt in: + +- omitted `contributions` produces the same client context, headers, query keys, and generated + result keys as today; +- `ServiceClient` and existing query types retain default generics; +- `propagateTraceContext` and `traceHeaders` remain transport-owned and supported; +- `defineServices()` creates the same three maps for contribution-free services; and +- the optional plugin manifest group does not invalidate old manifests. + +`port` and `timeout` remain accepted temporarily but are documented and annotated deprecated because +current code ignores them. This RFC does not give them new semantics. `port` migrates to +service-discovery configuration or the future explicit transport seam; request timeouts migrate to +an `AbortSignal` once the dedicated transport change is implemented. Removal requires the normal +breaking-change process. + +Existing hand-written auth wrappers migrate by moving per-call credential access into an auth-core +contribution and attaching its literal tuple. Existing hardcoded trace propagation does not migrate. +Generated projects change only when the user selects a contributor. + +Because this RFC changes public and publish surfaces, implementation packages must bump versions +according to the release plan and pass JSR isolated-declaration gates. No implementation is allowed +to publish an `@orpc/*` type in a generated `.d.ts`/JSR declaration. + +### Staged implementation plan and issue decomposition + +Implementation remains outside this RFC PR. + +| Stage | Existing owner | Scope and exit condition | +| -------------------------- | ----------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| 0. Ratify | [#1348](https://github.com/rickylabs/netscript/issues/1348) | Accept this RFC, settle safe FCP questions, and reconcile child issue bodies. | +| 1. Contract/type repair | [#1350](https://github.com/rickylabs/netscript/issues/1350) | Preserve the concrete base error map and initialize/export `NetScriptProcedureMeta`; type fixtures prove both. | +| 2. Minimal client seam | [#1349](https://github.com/rickylabs/netscript/issues/1349) | Add descriptor/helper, tuple algebra, context-generic client/query surfaces, native header composition, cache-effect handling, and failures. Do not expose upstream callback arrays. | +| 3. Transport consolidation | [#1351](https://github.com/rickylabs/netscript/issues/1351) | Recheck stable oRPC, update the family coherently, keep one fetch/retry/dedupe/trace path, and deprecate current no-op options. | +| 4. Auth dogfood | [#1352](https://github.com/rickylabs/netscript/issues/1352) | Ship the auth-core bearer factory, access metadata behavior, redaction, cache partition/direct-only modes, manifest reference, docs, and scaffold choice. | +| 5. Trace ownership proof | [#1353](https://github.com/rickylabs/netscript/issues/1353) | Re-scope from “trace contribution” to prove the transport retains the only final trace injection and rejects contributor ownership of trace headers. | +| 6. Non-auth proof | new child after RFC acceptance | Ship/test locale contribution, partitioned keys, header conflicts, and generated use. Do not file during this RFC run. | +| 7. Generic discovery | [#1093](https://github.com/rickylabs/netscript/issues/1093) | Discover third-party module references without hardcoded factories; generated selection remains explicit. | + +Issue #451 remains the sole future owner of custom links. #928 and #934 consume aligned protocol and +metadata vocabulary but are not prerequisites for the header seam. The org-aware policy work in +[#884](https://github.com/rickylabs/netscript/issues/884) may later add a tenant context/header +contribution, but server authorization and tenant validation remain separate. + +### Conformance and fitness gates + +An implementation is not complete until all applicable gates pass. + +#### Type gates + +- context-free, optional-context, and required-context direct calls; +- two disjoint contributions intersect correctly; +- duplicate id, context key, header key, reserved header, missing context key declaration, and + 17-element tuple have `@ts-expect-error` fixtures; +- `defineServices`, server query factories, TanStack query/infinite/mutation options, and `.call` + preserve the per-service context; +- `direct-only` service keys are absent from query/query-utils mapped types; +- server-defined error inference remains exact after metadata initialization; and +- public declarations contain no upstream oRPC type. + +#### Runtime gates + +- async preparation, omission, deterministic first failure, abort, and zero-dispatch-on-failure; +- duplicate validation repeated through `unknown`/JavaScript input; +- undeclared, mixed-case, forbidden, CR/LF, non-string, and duplicate headers rejected; +- base `Content-Type` and final trace fields cannot be overwritten; +- a retry reuses one prepared result; +- locale and two auth partitions cannot share cached data, while prefix invalidation still works; +- direct-only services have no runtime query/query-utils property; and +- every error/log/span snapshot excludes header values, input, context, partitions' source values, + source messages, tokens, and session ids. + +#### Plugin/generated gates + +- a synthetic third-party manifest contributes a module/export without a core edit; +- duplicate/mismatched ids and target-incompatible exports fail `plugin doctor`/generation; +- generated code uses public exports, static imports, `as const`, and explicit service selection; +- removing auth from generated config removes the context requirement and wire header; and +- auth and locale scaffold doctests type-check. + +#### Repository and publish gates + +- scoped check/lint/fmt wrappers for changed TypeScript; +- focused package tests, `deno task arch:check`, and docs/RFC link/lint checks; +- `deno doc --lint` for every affected public module; +- `deno publish --dry-run --allow-dirty` and the repository JSR audit for `contracts`, `sdk`, + `plugin`, and `plugin-auth-core`; +- clean consumer install/type probe against packed/published surfaces; and +- full `deno task e2e:cli run scaffold.runtime --cleanup --format pretty` only at implementation + merge readiness, not for this docs-only RFC PR. + +### Documentation and scaffold implications + +Implementation updates must cover: + +- SDK root/client/ports API docs and README examples; +- auth-core SDK/server/browser export boundaries and credential/redaction guidance; +- contract metadata and the distinction between client guidance and server enforcement; +- plugin manifest/config builder documentation; +- generated service-client templates and embedded CLI assets; +- query partition visibility, direct-only behavior, and cache invalidation; +- CORS/preflight, cleartext bearer, cookie, redirect, and retry limitations; and +- migration notes for manual header wrappers and deprecated `port`/`timeout` fields. + +Scaffolds must ask which services receive an available contribution. Installing auth alone does not +attach credentials globally. No generated source contains a credential, session identifier, or +environment-derived secret. + +## Drawbacks + +- The descriptor, validation, errors, and cache-effect declaration add public concepts for what is + ultimately an HTTP header callback. +- Requiring exclusive ownership prevents deliberate multi-value cooperation on one header. That is a + conscious version-1 constraint; a first-class header-specific combiner would need its own law. +- A required response-cache declaration burdens simple contributors, but omitting it would make + auth-aware caching unsafe by default. +- `direct-only` can remove expected query helpers. A loud absence is preferable to cross-user cache + reuse or a property that fails only under load. +- Static plugin selection is less magical than auto-activation, but generated/app config remains + auditable and type-inferred. +- The fixed tuple limits may be reached by unusually extension-heavy services. + +## Rationale and alternatives + +### Why this boundary + +Headers plus typed per-call context are the smallest seam proven by two different consumers. They +map directly to an existing public oRPC callback, can be represented without upstream types, and do +not grant plugins transport control. The cache-effect field is not another behavior hook; it is the +minimum declaration needed to keep existing query surfaces safe. + +### Rejected: the starting “one envelope for everything” proposal + +The proposed envelope put headers, three interceptor/plugin stages, `fetch`, link, errors, server +plugins, metadata, and query behavior behind one name. Those fields have different owners, +lifecycles, failure modes, and compatibility risks. Passing them through would make NetScript's +public API an unstable mirror of oRPC and would legitimize per-plugin transport stacks. This RFC +keeps only the capability with two demonstrated consumers. + +### Rejected: expose `headers` directly on `CreateServiceClientOptions` + +A raw callback solves one app but provides no stable id, context algebra, ownership conflict, +version negotiation, plugin reference, response-cache declaration, or generated composition. It also +invites each new need to add another unrelated option. + +### Rejected: oRPC link plugins/interceptors as the public contribution + +They can intercept lifecycle stages, but they do not declare added context keys, header ownership, +cache variance, plugin identity, or protocol compatibility. Re-exporting them also violates the +upstream-type-free port rule. NetScript can continue to use them internally. + +### Rejected: last writer wins, priorities, and dependency ordering + +These make plugin load order semantic and create non-local failures. Version 1 contributions see the +same snapshot and own disjoint keys, so successful composition is order-independent. A future +cooperative header protocol needs a separate RFC, not a priority number. + +### Rejected: trace propagation as the non-auth contribution + +Trace headers look like the same shape but are injected at the wrong lifecycle point. The SDK's +client span is created in the transport `fetch`; the outgoing `traceparent` must name that span. +Keeping trace transport-owned also prevents a plugin from silently breaking distributed traces. +Locale proves generality without duplicating credential semantics or violating trace ownership. + +### Rejected: contribution-defined error maps + +A client header preparer cannot add errors to a server contract. Local failures occur before a +server response and must remain distinguishable from type-safe contract errors. Error-map repair is +still necessary, but it is orthogonal. + +### Rejected: arbitrary query defaults and invalidation callbacks + +The SDK already has server and TanStack query APIs. Allowing contributions to author defaults or key +fragments would create a third policy owner and preserve the repository's existing dual-key problem. +Version 1 only appends a canonical safety partition and otherwise leaves query behavior alone. + +### Rejected: automatic plugin activation + +Ambient discovery would attach credentials and policy to services by installation side effect, make +inference depend on runtime state, and complicate browser/server boundaries. Static discovery plus +explicit generated selection is auditable and tree-shakeable. + +### Rejected: fluent client builder or global registry + +A builder makes the generated tuple harder to infer and serialize as source. A process-global +registry risks test isolation, request leakage, and hidden ordering. The literal tuple is the +composition root. + +### Impact of doing nothing + +Auth remains a hardcoded wrapper or global token, non-auth headers require SDK forks, third-party +plugins require core switches, and generated/query clients cannot carry a sound request context. + +## Breaking changes and migration + +The ratified surface is additive when unused. Opting into a required-context contribution changes +that service's call signature by design. Opting into `direct-only` removes that service from +generated query maps by design. Those changes are local, inferred consequences of explicit config, +not ambient breaking changes. + +The implementation should land in minor, coherent package releases. It must not combine removal of +`port`, `timeout`, or trace compatibility fields with this addition. Any later removal or public +custom-link design gets its own breaking assessment. + +## Prior art + +- oRPC's [RPCLink](https://orpc.dev/docs/client/rpc-link) provides async headers from typed client + context and exposes path/input to the callback. This RFC composes that capability once. +- oRPC [metadata](https://orpc.dev/docs/metadata) initializes a typed metadata vocabulary with + `$meta()` and exposes it on procedures. NetScript owns the narrower cross-package type. +- oRPC's TanStack integration already requires non-empty client context in query options. NetScript + currently erases it; this RFC restores it without exposing upstream utility types. +- The WHATWG [Fetch Standard](https://fetch.spec.whatwg.org/#forbidden-request-header) defines + request-header ownership that browser code cannot override; runtime validation follows it. +- W3C [Trace Context](https://www.w3.org/TR/trace-context/) explains why trace headers have + mutation, privacy, and trust-boundary rules beyond ordinary app headers. +- NetScript's existing plugin contribution groups establish the named registration pattern, and its + doctrine requires deterministic load plus rejection of semantic plugin-order dependence. + +## Unresolved questions + +These are safe for discussion/FCP because they do not change the extension law: + +1. Should the first implementation reserve exactly 16 contributions, or raise the ceiling if CI type + fixtures demonstrate equal cost? It must not ship below 16. +2. Should an environment-reading bearer convenience factory ship in the first auth slice or remain + an application example? If shipped, it must use an explicit server-only export and the same + redaction/transport rules. +3. Should #451 be rescheduled alongside implementation, or remain independent? This RFC neither + exposes nor requires a custom link. +4. Maintainers may refine public names (`responseCache`, `direct-only`, or the access enum) during + FCP while preserving the specified semantics and defaults. + +The following are not open: duplicate rejection, order independence, per-call async preparation, +reserved trace ownership, no upstream callback arrays, explicit plugin selection, cache partition +safety, and separation from contract-defined errors. + +## Future possibilities + +- A separately ratified body-signing stage after stable encoded bytes exist. +- A custom-link API based on the existing package-owned port and explicit capabilities (#451). +- Cooperative multi-value header combiners with a header-specific composition law. +- Safe `401` credential refresh with idempotency/replay policy. +- Tenant, idempotency, request-priority, or feature-negotiation contributions. +- A unified query-key implementation underneath the two public query surfaces, without changing this + contribution protocol. +- Additional `NetScriptProcedureMeta` fields for gateway and org-aware policy, governed by their + owning RFCs. From e78ac0a65f5475ed37152272b16ba7d89deca8c3 Mon Sep 17 00:00:00 2001 From: Rickylabs Date: Sat, 8 Aug 2026 19:38:06 +0200 Subject: [PATCH 03/12] docs(rfc): finalize evaluator handoff --- .../context-pack.md | 21 +-- .../final-handoff.md | 139 ++++++++++++++++++ .../plan.md | 2 +- .../supervisor.md | 34 +++-- .../worklog.md | 35 +++-- 5 files changed, 191 insertions(+), 40 deletions(-) create mode 100644 .llm/runs/docs-rfc-sdk-client-contribution--rfc/final-handoff.md diff --git a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/context-pack.md b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/context-pack.md index 93e03ba6e4..9a65dc34a8 100644 --- a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/context-pack.md +++ b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/context-pack.md @@ -2,14 +2,14 @@ ## Run Metadata -| Field | Value | -| -------------- | ---------------------------------------------------------------------- | -| Run ID | `docs-rfc-sdk-client-contribution--rfc` | -| Branch | `docs/rfc-sdk-client-contribution` | -| Current phase | RFC authored; final evidence/reconciliation before `plan-eval` handoff | -| Archetype | `2 + 4 + 5 + 6` described; docs-only PR | -| Scope overlays | `SCOPE-docs` | -| PR | `https://github.com/rickylabs/netscript/pull/1390` | +| Field | Value | +| -------------- | ------------------------------------------------------ | +| Run ID | `docs-rfc-sdk-client-contribution--rfc` | +| Branch | `docs/rfc-sdk-client-contribution` | +| Current phase | `plan-eval`; awaiting owner-directed Fable/Qwen review | +| Archetype | `2 + 4 + 5 + 6` described; docs-only PR | +| Scope overlays | `SCOPE-docs` | +| PR | `https://github.com/rickylabs/netscript/pull/1390` | ## Current State @@ -69,7 +69,7 @@ primary upstream sources are recorded. No product source is changed. | Doc-lint baseline | baseline finding | combined private refs 9/3/15/4 respectively; RFC adds none | | Doctrine | pass | `deno task arch:check` exits 0; existing warnings are baseline | | Plan Gate self-audit | pass | complete for external evaluator entry; no evaluator verdict claimed | -| Final PR reconciliation | pending | slice 3 | +| Final PR reconciliation | pass | draft, required labels, sole `status:plan-eval`, no milestone/closing keyword | ## JSR Consequences @@ -105,4 +105,5 @@ milestones. Findings should cite RFC headings and classify blocking versus safe ## Commits - Bootstrap: `158849031bba78025d0ec16c8361628211fbc4ed`. -- Later commits and per-slice PR comments are the authoritative V3 commit record. +- RFC/research: `89ae608ea935ba8b2776d55e7cb5a09cc29e2520`. +- The handoff-only commit and per-slice PR comments complete the V3 commit record. diff --git a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/final-handoff.md b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/final-handoff.md new file mode 100644 index 0000000000..8a8c337b36 --- /dev/null +++ b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/final-handoff.md @@ -0,0 +1,139 @@ +# Final Handoff: typed SDK client contributions RFC + +## Delivery Identity + +| Field | Value | +| ------------------- | ----------------------------------------------------------- | +| Draft PR | `https://github.com/rickylabs/netscript/pull/1390` (#1390) | +| Branch | `docs/rfc-sdk-client-contribution` | +| Base | `origin/main` at `fac9e339042c5394bf882311657d8981d353a1c3` | +| Reviewable RFC HEAD | `89ae608ea935ba8b2776d55e7cb5a09cc29e2520` | +| RFC | `rfcs/0000-sdk-client-contributions.md` (`0000`, Draft) | +| Run dir | `.llm/runs/docs-rfc-sdk-client-contribution--rfc/` | +| PR phase | `status:plan-eval` | + +`89ae608ea935ba8b2776d55e7cb5a09cc29e2520` is the exact substantive RFC/research commit reviewed by +the generator gates. The commit containing this handoff changes run metadata only; its pushed SHA is +recorded in the S3 PR comment so the handoff does not pretend it can contain its own Git object id. + +## Outcome + +The carried-in Fable proposal was challenged rather than copied. The RFC ratifies a narrow, +package-owned request-header preparation axis over oRPC's existing async headers/context seam. It +does not authorize a generic client middleware, raw-link, transport, query-policy, error-map, or +server-plugin framework. + +## Decisions Made + +1. A contribution has protocol `{ family: "netscript.sdk-client", major: 1 }`, a validated id, + runtime required/optional context declaration, exclusive lower-case header keys, a mandatory + response-cache effect, and async `prepare`. +2. A literal tuple infers one context intersection per service. Duplicate id, context, header, + reserved ownership, invalid limits, and widened/JavaScript boundary errors fail explicitly. +3. Contributors run sequentially against the same immutable snapshot and cannot see accumulated + output. Valid disjoint results commute; tuple order selects only the first reported failure. +4. Query use is safe by construction: `invariant`, synchronous non-secret `partitioned`, or + `direct-only`. Partition pairs are id-sorted full-key suffixes; direct-only services are absent + from query/query-utils maps. +5. `@netscript/plugin-auth-core/sdk` owns the bearer factory. Procedure metadata is + `NetScriptProcedureMeta.access.authentication = "none" | "optional" | "required"`, with + first-party unmarked behavior defaulting to `"none"`. +6. Locale/`accept-language` is the non-auth proof. Trace was rejected as dogfood because final W3C + trace fields belong to the client-span transport edge. +7. Discovery adds static module/export/target availability through `@netscript/plugin/config`; + generated/application config explicitly activates literal tuples per service. +8. Discovery, codecs, fetch, retry, dedupe, cancellation, redirects, tracing, and server-defined + errors remain SDK transport policy. Custom links remain exclusively #451. +9. Contribution failures are local stable errors with a fixed diagnostic allowlist. Header values, + input, context, partition source values, resolver messages, and resolver causes do not cross the + error/log/telemetry boundary. +10. Omitted contributions preserve current context, headers, query keys, and mapped result keys. + Existing generic call sites retain defaults; current no-op `port`/`timeout` fields are + deprecated but not removed by this RFC. + +## FCP-Safe Unresolved Questions + +Only these questions remain open: + +1. Raise the 16-contribution ceiling if CI type evidence supports it; do not ship below 16. +2. Ship an explicit server-only environment credential helper in the first auth slice or keep it as + an application example. +3. Schedule independent custom-link issue #451 alongside implementation or later. +4. Refine public names during FCP without changing defaults, ownership, cache safety, or composition + semantics. + +Duplicate rejection, order independence, per-call async preparation, reserved trace ownership, no +upstream callback arrays, explicit activation, cache safety, and separation from contract-defined +errors are not open. + +## Validation Evidence + +| Gate | Result | +| ------------------------ | ------------------------------------------------------------------------------------------------------- | +| Exact base/merge-base | PASS at `fac9e339042c5394bf882311657d8981d353a1c3` | +| RFC/harness formatting | PASS, eight tracked Markdown files checked | +| Focused RFC links | PASS, 1 document, 0 broken links/anchors | +| Repository docs links | PASS, 102 documents, 0 broken links/anchors | +| Docs accuracy | PASS | +| Exact-shape type proof | PASS; required/optional context, conflicts, 16 accepted, 17 rejected | +| Doctrine | PASS, `deno task arch:check` exit 0 | +| Diff hygiene | PASS, `git diff --check` | +| Review-thread gate | PASS, 0 threads / 0 unanswered | +| Package publish dry-runs | PASS for contracts, SDK, plugin, and auth core | +| JSR package audit | contracts/SDK/auth core exit 0; plugin exit 1 on four pre-existing module-tag plus cardinality findings | +| Structured doc lint | Pre-existing private refs: contracts 9, SDK 3, plugin 15, auth core 4 | + +The JSR/doc-lint findings are implementation baselines, not failures introduced by this docs PR and +not waivers. No runtime/scaffold E2E was run because this RFC changes no framework or generated +source; the RFC assigns the full one-pass runtime gate to implementation merge readiness. + +## Board Reconciliation Proposal + +No issue or milestone was mutated. After RFC acceptance, the maintainer/root orchestrator should: + +1. reconcile #1348 acceptance with the narrow header/context/cache law; +2. narrow #1349 to descriptor, composer, context/query propagation, and cache safety; +3. keep #1350 as exact base error-map plus metadata repair; +4. keep #1351 as SDK-owned transport consolidation and coherent oRPC-family update; +5. place bearer convention, redaction, and auth delivery under #1352; +6. re-scope #1353 from a trace contribution to trace ownership/reserved-header conformance; +7. file the locale proof child only after acceptance; +8. cross-link generic discovery #1093; and +9. keep custom link #451 and later #928/#934/#884 work independent except for shared vocabulary. + +## Exact Fable Reviewer Instructions + +Use the already-existing Claude Fable 5 session reserved by the root orchestrator. Do not launch a +new authoring or evaluator session from this branch. + +Read in this order: + +1. `rfcs/0000-sdk-client-contributions.md`; +2. `research.md`, especially the proposal challenge, current API evidence, board state, upstream + sources, type probe, and JSR consequences; +3. `plan.md`, including the locked decisions, risks, Plan Gate self-audit, and issue map; +4. `worklog.md` `## Design` and exact gate table; +5. `drift.md`; and +6. the carried proposal at + `/home/codex/repos/netscript-fable5-remediation-plan/.llm/runs/plan-fable5-remediation-roadmap--seed/fable-5-remediation-plan/rfcs/RFC-A-sdk-client-composition.md`. + +Perform a cross-RFC Plan & Design review, not implementation. Specifically try to falsify: + +- minimality against current oRPC/NetScript seams; +- tuple inference and widened/runtime validation at the stated budgets; +- order independence and duplicate/reserved ownership law; +- auth and locale cache isolation across direct, server-query, and TanStack paths; +- redaction, cleartext, redirect, abort, and retry guarantees; +- transport/final-trace ownership and #451 separation; +- static plugin availability versus explicit activation; and +- compatibility, JSR declaration boundaries, staged issue ownership, and executable gates. + +For every finding, cite an RFC heading and repository/upstream evidence, classify it as blocking or +FCP-safe, and state the smallest correction. Explicitly say whether both auth and locale can be +implemented without adding a parallel framework. Record the observed reviewer identity, verdict, and +required RFC edits in the harness artifacts and a structured PR comment. Do not assign an RFC +number, implement package code, merge, close/create issues, mutate milestones, or move the PR past +the review lifecycle on the generator's behalf. + +After Fable findings are reconciled, the root orchestrator—not this generator—should run the planned +Qwen adversarial pass against the revised RFC and the Fable verdict. diff --git a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/plan.md b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/plan.md index d253c95f91..5eefa81eaf 100644 --- a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/plan.md +++ b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/plan.md @@ -6,7 +6,7 @@ | -------------- | ------------------------------------------------------------------------------------------------------------ | | Run ID | `docs-rfc-sdk-client-contribution--rfc` | | Branch | `docs/rfc-sdk-client-contribution` | -| Phase | RFC authored; evidence/gates and external-review handoff remain | +| Phase | `plan-eval`; owner-directed external review is the next action | | Target | `rfcs/0000-sdk-client-contributions.md` plus mandatory harness artifacts | | Archetype | `2 Integration`; `4 Public DSL / Builder`; `5 Plugin`; `6 CLI / Tooling` (described implementation surfaces) | | Scope overlays | `SCOPE-docs` | diff --git a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/supervisor.md b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/supervisor.md index b35d6d64eb..2e5861b570 100644 --- a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/supervisor.md +++ b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/supervisor.md @@ -2,24 +2,24 @@ Written at run start per `workflow/lane-policy.md` § Supervisor identity. -| Field | Value | -| --- | --- | -| Model | Codex · OpenAI · GPT-5.6 Sol · xhigh | -| Session | `019fe242-2bd9-7ff3-8044-bd9d09585397` | -| Host | native WSL Linux · user `codex` · full-access / approval `never` | -| Checkout | `/home/codex/repos/ns-rfc-sdk-client` | -| Worktree | `/home/codex/repos/ns-rfc-sdk-client` | -| Branch | `docs/rfc-sdk-client-contribution` (no upstream by design) | +| Field | Value | +| -------- | -------------------------------------------------------------------------------- | +| Model | Codex · OpenAI · GPT-5.6 Sol · xhigh | +| Session | `019fe242-2bd9-7ff3-8044-bd9d09585397` | +| Host | native WSL Linux · user `codex` · full-access / approval `never` | +| Checkout | `/home/codex/repos/ns-rfc-sdk-client` | +| Worktree | `/home/codex/repos/ns-rfc-sdk-client` | +| Branch | `docs/rfc-sdk-client-contribution` (no upstream by design) | | Baseline | `origin/main` @ `fac9e339042c5394bf882311657d8981d353a1c3` (verified 2026-08-08) | -| Run ID | `docs-rfc-sdk-client-contribution--rfc` | +| Run ID | `docs-rfc-sdk-client-contribution--rfc` | ## Routes in force -| Task lane | Provider / model / effort | Role in this run | -| --- | --- | --- | -| Owner-directed RFC generator | OpenAI / GPT-5.6 Sol / xhigh | Sole researcher and RFC author; daemon-attached session above | -| Owner-directed cross-RFC review | Existing Anthropic / Claude Fable 5 session; identity to be recorded by root orchestrator | Separate-session RFC/plan review after generator handoff; this session must not launch it | -| Owner-directed final adversarial pass | Qwen route selected and launched by root orchestrator | Separate-session final review after Fable; this session must not launch it | +| Task lane | Provider / model / effort | Role in this run | +| ------------------------------------- | ----------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- | +| Owner-directed RFC generator | OpenAI / GPT-5.6 Sol / xhigh | Sole researcher and RFC author; daemon-attached session above | +| Owner-directed cross-RFC review | Existing Anthropic / Claude Fable 5 session; identity to be recorded by root orchestrator | Separate-session RFC/plan review after generator handoff; this session must not launch it | +| Owner-directed final adversarial pass | Qwen route selected and launched by root orchestrator | Separate-session final review after Fable; this session must not launch it | ## Recorded lane/eval overrides @@ -33,3 +33,9 @@ Written at run start per `workflow/lane-policy.md` § Supervisor identity. `codex-thread-ids.md` and rollout path provide the concrete daemon-attached identity; no daemon repair or rival launch is authorized. +## Handoff State + +- Generator work is complete at draft PR #1390 and `status:plan-eval`. +- Reviewable RFC/research commit: `89ae608ea935ba8b2776d55e7cb5a09cc29e2520`. +- The exact Fable entry point and prohibited mutations are in `final-handoff.md`. +- No evaluator was launched and no external verdict is claimed by this session. diff --git a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/worklog.md b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/worklog.md index ed968232c4..23e0fa5f53 100644 --- a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/worklog.md +++ b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/worklog.md @@ -138,7 +138,9 @@ considered complete. | 2026-08-08 | 2 | JSR baseline | Four package dry-runs OK; structured doc-lint/private-type baselines and existing plugin audit failure recorded. | | 2026-08-08 | 3 | doctrine | `deno task arch:check` exits 0; warning-only package debt is pre-existing and remains unwaived. | | 2026-08-08 | 3 | plan gate | Self-audit covers current state/gap, alternatives, exact surface, laws, failures, migration, slices/issues, and gates; no evaluator verdict claimed. | -| 2026-08-08 | 3 | final docs/type | Re-ran exact-shape type proof, six-file format check, 102-document links, docs accuracy, focused RFC links, and diff hygiene; all pass. | +| 2026-08-08 | 3 | final docs/type | Re-ran exact-shape type proof, eight-file format check, 102-document links, docs accuracy, focused RFC links, and diff hygiene; all pass. | +| 2026-08-08 | 3 | RFC commit | Committed/pushed `89ae608ea935ba8b2776d55e7cb5a09cc29e2520`; posted structured research and plan summaries. | +| 2026-08-08 | 3 | PR reconciliation | Draft PR has all required labels, sole `status:plan-eval`, no milestone/closing keyword; review-thread gate passes 0/0. | ## Decisions @@ -166,20 +168,23 @@ considered complete. ## Gate Results -| Gate | Command | Result | -| --------------------- | ---------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | -| RFC format | `deno fmt --check rfcs/0000-sdk-client-contributions.md` | PASS after format | -| Focused RFC links | link checker with `--root rfcs/0000-sdk-client-contributions.md` | PASS, 0 broken links/anchors | -| Repository docs links | `deno task docs:links` | PASS, 102 docs, 0 broken links/anchors | -| Docs accuracy | `deno task docs:accuracy` | PASS | -| Type proof | `deno check --config .llm/tmp/deno.json .llm/tmp/sdk-client-contribution-probe.ts` | PASS | -| Package audit | four `audit-jsr-package.ts --text` runs | contracts/sdk/auth-core exit 0; plugin exit 1 on pre-existing 4 module-tag + cardinality findings; all dry-runs OK | -| Structured doc lint | four `run-deno-doc-lint.ts` runs | baseline private refs: contracts 9, SDK 3, plugin 15, auth-core 4; report command exits 0 | -| Doctrine | `deno task arch:check` | PASS, exit 0; existing warning-only package debt recorded and not waived | -| Plan Gate self-audit | checklist against `plan-gate.md` and RFC required sections | PASS for evaluator entry; not a PLAN-EVAL verdict | -| Diff hygiene | `git diff --check` | PASS | - -Live PR reconciliation remains pending rather than implied complete. +| Gate | Command | Result | +| --------------------- | ----------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | +| RFC format | `deno fmt --check rfcs/0000-sdk-client-contributions.md` | PASS after format | +| Focused RFC links | link checker with `--root rfcs/0000-sdk-client-contributions.md` | PASS, 0 broken links/anchors | +| Repository docs links | `deno task docs:links` | PASS, 102 docs, 0 broken links/anchors | +| Docs accuracy | `deno task docs:accuracy` | PASS | +| Type proof | `deno check --config .llm/tmp/deno.json .llm/tmp/sdk-client-contribution-probe.ts` | PASS | +| Package audit | four `audit-jsr-package.ts --text` runs | contracts/sdk/auth-core exit 0; plugin exit 1 on pre-existing 4 module-tag + cardinality findings; all dry-runs OK | +| Structured doc lint | four `run-deno-doc-lint.ts` runs | baseline private refs: contracts 9, SDK 3, plugin 15, auth-core 4; report command exits 0 | +| Doctrine | `deno task arch:check` | PASS, exit 0; existing warning-only package debt recorded and not waived | +| Plan Gate self-audit | checklist against `plan-gate.md` and RFC required sections | PASS for evaluator entry; not a PLAN-EVAL verdict | +| Diff hygiene | `git diff --check` | PASS | +| PR metadata | live `gh pr view` | PASS: draft/main, required labels, exactly one `status:plan-eval`, milestone null, #1348 reference only | +| Review threads | `deno task agentic:review-threads -- --repo rickylabs/netscript --pr 1390 --pretty` | PASS, 0 threads / 0 unanswered | + +Generator gates and PR reconciliation are complete. External Fable/Qwen verdicts remain pending by +owner instruction. ## Handoff Notes From 7a0d398087a6608ff1a55bb9fe4c47158edb72a7 Mon Sep 17 00:00:00 2001 From: Rickylabs Date: Sat, 8 Aug 2026 19:57:05 +0200 Subject: [PATCH 04/12] docs(rfc): reconcile oRPC v2 audit --- .../context-pack.md | 53 ++- .../drift.md | 24 ++ .../plan.md | 43 +- .../research.md | 49 ++- .../supervisor.md | 11 +- .../worklog.md | 94 +++-- rfcs/0000-sdk-client-contributions.md | 385 ++++++++++++++---- 7 files changed, 528 insertions(+), 131 deletions(-) diff --git a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/context-pack.md b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/context-pack.md index 9a65dc34a8..d2340e58dd 100644 --- a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/context-pack.md +++ b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/context-pack.md @@ -16,7 +16,9 @@ The RFC is authored at `rfcs/0000-sdk-client-contributions.md` and keeps `0000`/Draft. It rejects the starting single “everything” envelope and ratifies a narrow, versioned request-header preparation axis. Research, type proof, current JSR/doc-lint baselines, live board state, and -primary upstream sources are recorded. No product source is changed. +primary upstream sources are recorded. A root-requested post-generator audit amendment now makes the +seam explicitly upstream-major-neutral, fixes the retry lifecycle, and separates the oRPC v2 +migration. This amendment is not an evaluator verdict. No product source is changed. ## Decision Snapshot @@ -34,6 +36,14 @@ primary upstream sources are recorded. No product source is changed. defaults to `none`. - SDK transport retains discovery/codec/fetch/retry/dedupe/trace/errors. Trace fields are reserved; #1353 is a trace-ownership proof, not a contribution. +- Public/generated declarations contain zero raw oRPC symbols. Three internal NetScript ports + isolate procedure metadata, prepared outbound headers, and transport policy. +- Preparation runs once per logical call above retry; each attempt sees byte-equivalent immutable + contributor headers/context. Outer wrapper versus memo is an internal Fable question. +- RFC-A implements against stable v1 (optionally v1.15.0 after a separate exact-family decision). v2 + beta/protocol/errors/GET/OTel/serialization/streaming migration is a separate RFC/spike. +- The server request-header handler is only an optional incoming companion and may be absent for + direct calls. - Plugin discovery registers static module/export/targets; generated/app config explicitly selects contributions per service. - Preparation failures are stable local errors, never server-defined contract errors. @@ -58,24 +68,29 @@ primary upstream sources are recorded. No product source is changed. ## Gate Snapshot -| Gate | Status | Evidence | -| ------------------------------ | ---------------- | ------------------------------------------------------------------------------- | -| RFC formatting | pass | `deno fmt --check` | -| RFC internal links | pass | focused repo link checker, 0 broken | -| Repository docs links/accuracy | pass | both tasks exit 0 | -| Type probe | pass | Deno check; 16 accepted/17 rejected fixture | -| Package dry-run baseline | pass | contracts/sdk/plugin/auth-core all report dry-run OK | -| JSR package audit | baseline finding | plugin audit exit 1 on pre-existing module tags/cardinality; other three exit 0 | -| Doc-lint baseline | baseline finding | combined private refs 9/3/15/4 respectively; RFC adds none | -| Doctrine | pass | `deno task arch:check` exits 0; existing warnings are baseline | -| Plan Gate self-audit | pass | complete for external evaluator entry; no evaluator verdict claimed | -| Final PR reconciliation | pass | draft, required labels, sole `status:plan-eval`, no milestone/closing keyword | +| Gate | Status | Evidence | +| ------------------------------- | ---------------- | ------------------------------------------------------------------------------- | +| RFC formatting | pass | `deno fmt --check` | +| RFC internal links | pass | focused repo link checker, 0 broken | +| Repository docs links/accuracy | pass | both tasks exit 0 | +| Type probe | pass | Deno check; 16 accepted/17 rejected fixture | +| Package dry-run baseline | pass | contracts/sdk/plugin/auth-core all report dry-run OK | +| JSR package audit | baseline finding | plugin audit exit 1 on pre-existing module tags/cardinality; other three exit 0 | +| Doc-lint baseline | baseline finding | combined private refs 9/3/15/4 respectively; RFC adds none | +| Doctrine | pass | `deno task arch:check` exits 0; existing warnings are baseline | +| Plan Gate self-audit | pass | complete for external evaluator entry; no evaluator verdict claimed | +| Audit amendment evidence | pass | 59-line input hashed; 91/74 file scan; seven v1 dependencies behind to 1.15.0 | +| Audit amendment gates | pass | format, links, accuracy, type proof, doctrine, and diff hygiene | +| Pre-amendment PR reconciliation | pass | draft, required labels, sole `status:plan-eval`, no milestone/closing keyword | +| Amendment PR reconciliation | pending | restore sole `status:plan-eval` after explicit-refspec push | ## JSR Consequences - No new contracts/SDK/plugin subpaths; root/client/ports/config symbols expand. - Auth core adds `./sdk` and possibly a constrained `./sdk/server` export. - No oRPC public type may leak into declarations. +- The stronger implementation gate is zero raw oRPC module specifiers or symbols in all public and + generated declarations. - Implementation must reduce or isolate existing private-type references, preserve precise error and metadata types, and pass doc-lint/publish/consumer gates. @@ -88,6 +103,9 @@ primary upstream sources are recorded. No product source is changed. 5. Re-scope #1353 to final trace injection/reserved-key conformance. 6. File a locale proof child only after acceptance. 7. Cross-link #1093 and keep #451 independent. +8. Propose, but do not file in this run, a separate oRPC v2 migration RFC/spike with stable/beta, + atomic family, rollout/endpoints, route/meta/OpenAPI/Scalar, error/status, middleware-count, + GET/CSRF, OTel, desktop serializer, streams, cache, runtime matrix, E2E, docs, and publish gates. ## External Reviewer Entry Point @@ -96,8 +114,9 @@ Read, in order: 1. `rfcs/0000-sdk-client-contributions.md`; 2. `research.md` proposal challenge and API/board evidence; 3. `plan.md` locked decisions, gates, and issue reconciliation; -4. `worklog.md` Design and gate results; and -5. `drift.md` for owner-authorized evaluator routing and design drift. +4. `worklog.md` Design and gate results; +5. `drift.md` for owner-authorized evaluator routing and design drift; and +6. `.llm/tmp/orpc-v2-audit-followup.md` as the root-requested post-generator research input. The reviewer must not implement product code, assign an RFC number, merge, close issues, or mutate milestones. Findings should cite RFC headings and classify blocking versus safe FCP feedback. @@ -106,4 +125,6 @@ milestones. Findings should cite RFC headings and classify blocking versus safe - Bootstrap: `158849031bba78025d0ec16c8361628211fbc4ed`. - RFC/research: `89ae608ea935ba8b2776d55e7cb5a09cc29e2520`. -- The handoff-only commit and per-slice PR comments complete the V3 commit record. +- Handoff baseline: `e78ac0a65f5475ed37152272b16ba7d89deca8c3`. +- The audit-amendment commit and per-slice PR comment complete the V3 commit record; its SHA is + recorded in the PR comment because an artifact cannot contain its own commit id. diff --git a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/drift.md b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/drift.md index 638c83e447..9149048c07 100644 --- a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/drift.md +++ b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/drift.md @@ -73,3 +73,27 @@ documentation. - **Action:** record exact baseline, forbid new regressions, and require #1350/contribution work to reduce or isolate private upstream refs rather than invoking the current baseline as a waiver. - **Evidence:** `research.md` JSR section; `worklog.md` gate table. + +## 2026-08-08 — Root oRPC v2 audit invalidated stable-v1-shaped adapter assumptions + +- **What:** The finished RFC correctly kept upstream types out of its public descriptor, but still + described v1 `RPCLink.headers` and `.$meta` too normatively and assumed link-header preparation + naturally occurred once before retries. +- **Source:** root-requested `.llm/tmp/orpc-v2-audit-followup.md`; official oRPC releases, v1-to-v2 + migration, request-header plugin, TanStack, error docs, and `v2.0.0-beta.25` codec/retry source. +- **Expected:** A NetScript-owned extension seam should survive upstream-major changes and preserve + one credential/context snapshot across a logical call. +- **Actual:** v2 replaces typed metadata initialization with `defineMeta` plugins; its protocol is + incompatible with v1; direct link headers resolve during encoding and the retry plugin re-enters + downstream per attempt. The incoming request-header plugin is optional and does not implement + outbound contribution policy. A repository scan found 74 non-test `@orpc/*` files, confirming that + migration is substantially broader than RFC-A. +- **Severity:** significant post-generator design drift; root-requested research amendment, not an + evaluator verdict. +- **Action:** make upstream-major neutrality normative; specify private NetScript metadata, + prepared-header, and transport-policy ports; require prepare-once above retry or immutable + per-logical-call memoization; implement RFC-A against stable v1; split v2 into a separate + RFC/spike with coordinated rollout, parity, telemetry, cache, runtime, E2E, and publish gates. +- **Evidence:** amended RFC sections “Procedure metadata,” “Internal adapter ports,” “Async context, + retries, and cancellation,” “Transport ownership and oRPC alignment,” “Compatibility and + migration,” and “Staged implementation plan and issue decomposition.” diff --git a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/plan.md b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/plan.md index 5eefa81eaf..5096886e4f 100644 --- a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/plan.md +++ b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/plan.md @@ -55,6 +55,8 @@ axis, grounded in the current repository and public upstream oRPC behavior. - Safe response-cache identity across direct, server-query, and TanStack paths. - Board reconciliation against #1348–#1353, #1093, #451, #928, #934, and #884 without mutation. - Current oRPC lock/stable state and an explicit inference ceiling. +- Post-generator v2 audit: incompatible wire major, retry callback lifecycle, metadata API change, + incoming request-header companion boundary, and the broad migration blast radius. ## Locked Decisions @@ -71,6 +73,10 @@ axis, grounded in the current repository and public upstream oRPC behavior. | Metadata | `NetScriptProcedureMeta.access.authentication = "none" \| "optional" \| "required"`; unmarked procedures default to `"none"`. | | Trace | Transport-owned and reserved; #1353 becomes trace-ownership conformance rather than a contribution. | | Transport | Discovery/codec/fetch/retry/dedupe/trace/error remain SDK-owned; raw oRPC callbacks and links are not descriptor fields. #451 stays separate. | +| Adapter ports | Three package-private NetScript responsibilities: procedure metadata, prepared outbound headers, and transport policy. Version-specific wiring is non-normative. | +| Retry lifecycle | Prepare exactly once per logical call above retries; immutable prepared header/context output is replayed byte-equivalently on every attempt. | +| Upstream major | Public/generated declarations contain zero raw oRPC symbols. Implement against stable v1; v1.15.0 sequencing is separate; v2 requires a separate RFC/spike. | +| Server companion | Incoming request-header handler is optional and separate; direct calls may have no request headers. It is not outbound contribution composition. | | Query policy | No arbitrary defaults/invalidation callbacks; only canonical full-key partition suffix and context propagation. | | Plugin discovery | Optional static module/export/target references; installation exposes availability, explicit generated config activates per service. | | Inference budget | 16 contributions/service, 8 context keys/contributor, 16 header keys/contributor; type proof recorded. | @@ -83,14 +89,21 @@ Every brief-named implementation fork is resolved in the RFC. Remaining question 1. a ceiling may be raised after CI type evidence but not lowered below 16; 2. server credential convenience export timing; -3. independent #451 scheduling; and -4. semantic-preserving public naming refinements. +3. independent #451 scheduling; +4. semantic-preserving public naming refinements; +5. outer wrapper versus immutable per-call memoization for the locked prepare-once invariant; +6. procedure-auth metadata ratification placement and incoming server-plugin default behavior; +7. v1.15.0 sequencing; and +8. questions owned by the separate v2 RFC: GET/CSRF, mixed-version endpoint strategy, and OTel + injection ownership. ## Risk Register | Risk | Mitigation / RFC gate | | ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- | -| Parallel abstraction or upstream leakage | Descriptor maps only to native async headers; no public oRPC types; doc-lint and declaration inspection. | +| Parallel abstraction or upstream leakage | Three NetScript internal ports; zero raw oRPC symbols in public/generated declarations; doc-lint and declaration inspection. | +| Retry refresh within one call | Prepare-once above retry or immutable per-call memo; forced retry gate asserts count 1 and byte-equivalent output. | +| Accidental v2 beta migration | Stable-v1 implementation boundary; separately owned v2 RFC/spike and atomic rollout/parity gate set. | | Tuple/context inference cost | Per-service tail recursion, 16 limit, named markers, type fixtures at 16/17. | | Auth special case | Locale consumer and generic header/context/cache law; auth factory is one constrained implementation. | | Cross-principal cache leak | Mandatory response-cache effect, id-sorted partition suffix, direct-only omission, two-principal tests. | @@ -121,7 +134,8 @@ Every brief-named implementation fork is resolved in the RFC. Remaining question ### Runtime second 1. Construction validation and reserved ownership. -2. Per-call preparation wrapper over the single oRPC header resolver. +2. Three internal ports and per-logical-call preparation above retry semantics; stable-v1 adapter + consumes only an immutable prepared record. 3. Canonical cache partitions/direct-only map omission. 4. Redacted errors, abort/retry behavior, and transport integration. @@ -145,6 +159,8 @@ The RFC contains the full future gate matrix. This docs PR runs: Framework implementation issues inherit type, runtime, redaction, cache isolation, plugin parity, JSR/publish/consumer, CLI/scaffold, architecture, and full runtime E2E gates enumerated in the RFC. +They also inherit the zero-oRPC-symbol declaration scan and stable-v1 adapter conformance. A later +v2 spike repeats that suite plus its separate rollout/error/OTel/route/serializer/streaming gates. ## Arch-Debt Implications @@ -166,12 +182,14 @@ unavoidable new deviation requires a debt entry with owner/exit criteria in its ## Plan Gate Self-Audit -The RFC plan is ready for external evaluation: it states the current implementation and gap, -compares the broad proposal with the existing oRPC seam and narrower alternatives, locks public +The amended RFC plan is ready for external evaluation: it states the current implementation and gap, +compares the broad proposal with existing stable-v1 evidence and narrower alternatives, locks public placement and composition/failure/security laws, names migration and compatibility behavior, maps implementation slices and issues, and defines executable fitness gates. The RFC carries no product -implementation and leaves only the four explicitly FCP-safe questions open. This is a generator -self-audit, not a PLAN-EVAL verdict; the owner-designated external reviewer remains authoritative. +implementation. The post-generator oRPC audit amendment fixes upstream-major neutrality and retry +lifecycle before exposing its implementation/sequencing questions to Fable. This is a generator +self-audit and root-requested research amendment, not a PLAN-EVAL verdict; the owner-designated +external reviewer remains authoritative. ## Dependencies and Board Reconciliation @@ -182,6 +200,10 @@ self-audit, not a PLAN-EVAL verdict; the owner-designated external reviewer rema - #1093 supplies generic discovery. - #451 remains the only custom-link issue. - #928/#934 align on protocol/metadata vocabulary but do not block the minimal seam. +- A new oRPC v2 RFC/spike is proposed after RFC-A review; none is filed or mutated in this run. It + owns stable/beta policy, atomic family versions, coordinated or parallel endpoints, route/meta/ + OpenAPI/Scalar, errors/status, middleware counts, GET/CSRF, OTel, desktop serialization, streams, + cache keys, runtime matrix, E2E, docs, and publish proof. ## Drift Watch @@ -190,3 +212,8 @@ self-audit, not a PLAN-EVAL verdict; the owner-designated external reviewer rema - Any auth helper placed in the thin plugin rather than auth core. - Any trace contributor that can author `traceparent`/`tracestate`. - Any generated activation based only on installation or runtime scanning. +- Any public/generated declaration containing a raw oRPC type, module, callback, context, plugin, + interceptor, or metadata accessor. +- Any adapter that invokes contribution preparation once per retry rather than once per logical + call. +- Any RFC-A implementation PR that bundles an oRPC v2 beta, error/status, or OTel migration. diff --git a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/research.md b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/research.md index 88efd8164f..a299f16223 100644 --- a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/research.md +++ b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/research.md @@ -78,13 +78,35 @@ No issue, milestone, or lifecycle record was mutated in research. The PR is the | `deno.lock` and Deno cache declarations | The workspace resolves the oRPC family to 1.14.6. `ClientOptions` has signal/lastEventId/context; `RPCLinkOptions` composes native headers, link plugins, interceptors, and fetch capabilities. | | `deno task deps:latest -- --filter '@orpc/*'` | Stable-channel report: seven oRPC packages are behind; `^1.14.6`/`^1.14.7` → `1.15.0` on 2026-08-08. Implementation must recheck rather than hardcode this future value. | | `deno task deps:why -- @orpc/client` | Nine source hits; the dependency is live and not removable. | -| | Official docs show async headers from typed client context and method/fetch decisions from context/path. | -| | Official docs show `$meta()` initialization and procedure `~orpc.meta` consumption. | +| | Official stable-v1 docs show async headers from typed client context and method/fetch decisions from context/path. | +| | Official stable-v1 docs show `$meta()` initialization and procedure metadata consumption; this is adapter evidence only. | | | Normative forbidden header list plus `proxy-`/`sec-` prefix ownership. | | | Final trace mutation, privacy, and trust-boundary rules support transport ownership. | | | HTTP credentials rely on secured transport for confidentiality. | | OWASP Logging Cheat Sheet | Access tokens/session identifiers are excluded from direct logging. | +### Root-requested post-generator oRPC v2 audit amendment + +This is a research amendment requested by the root orchestrator after generator completion. It is +not a formal PLAN-EVAL verdict and no evaluator was launched. The supplied audit follow-up was read +in full (59 lines; SHA-256 `fa8b0ab5cd1afd57b8f6c20036a265fa7c8fb48764f88f97f289c44c0737d3d0`). Its +claims were reconciled against official upstream sources and current repository state: + +| Evidence | Reconciled conclusion | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Official releases](https://github.com/middleapi/orpc/releases) | `v2.0.0-beta.26` superseded `beta.25` and remains pre-release; `v1.15.0` is latest stable on the audit date. Do not migrate production to beta for RFC-A. | +| [v1-to-v2 migration guide](https://v2.orpc.dev/docs/migrations/from-v1) | The RPC protocol is incompatible across majors; `.$meta` becomes `defineMeta` plugins; middleware deduplication, error/status, GET/CSRF, links, serializers, OpenAPI, TanStack, and OTel all change. A v2 rollout is coordinated migration scope. | +| [Request headers plugin](https://v2.orpc.dev/docs/plugins/request-headers) | `RequestHeadersHandlerPlugin` is an optional incoming server companion and request headers can be absent on direct calls. It does not solve outbound composition. | +| [TanStack integration](https://v2.orpc.dev/docs/integrations/tanstack-query#client-context) | v2 still excludes client context from query keys; RFC-A's partition/direct-only law remains necessary. | +| [v2 error handling](https://v2.orpc.dev/docs/error-handling) and [client error handling](https://v2.orpc.dev/docs/client/error-handling) | Typed-error factories, HTTP status maps, and client inference changes belong to the v2 migration, not RFC-A contribution failures. | +| [`beta.25` standard link codec](https://github.com/middleapi/orpc/blob/v2.0.0-beta.25/packages/client/src/adapters/standard/rpc-link-codec.ts) and [retry plugin](https://github.com/middleapi/orpc/blob/v2.0.0-beta.25/packages/client/src/plugins/retry.ts) | Headers resolve during encoding and retry invokes downstream per attempt. Direct link-header preparation executes per retry; RFC-A must prepare above retry or memoize per logical call. | +| `rg -l '@orpc/' packages plugins` | 91 files contain references; 74 remain after excluding test paths/name patterns. The affected production surface is materially larger than RFC-A and includes SDK, service, contracts, plugins, telemetry, Fresh/desktop, CLI/scaffold, serializers, OpenAPI, errors, and queries. | +| `deno task deps:latest --filter '@orpc/*'` | Seven workspace dependencies on v1.14.x are behind stable v1.15.0. Any exact-family v1 upgrade is a separate low-risk sequencing decision. | + +The amendment locks upstream-major neutrality and three internal NetScript adapter responsibilities: +procedure metadata, prepared outbound headers, and transport policy. Stable v1 is the implementation +target. A v2 adapter must be designed and gated in a separate RFC/spike. + ## Proposal challenge record | Starting proposal choice | Verdict | Reason | @@ -120,7 +142,15 @@ No issue, milestone, or lifecycle record was mutated in research. The PR is the headers are reserved. 9. Plugin manifests carry static module/export/target references; generators use explicit imports and literal tuples. No ambient activation. -10. No product implementation belongs in this RFC PR. +10. Public contribution types and generated declarations are upstream-major-neutral and contain zero + raw oRPC symbols. Package-private metadata, prepared-header, and transport-policy ports isolate + version-specific adapters. +11. Preparation runs exactly once per logical call above retry semantics. The immutable prepared + header/context snapshot is reused byte-equivalently on every attempt. +12. RFC-A implements on stable v1. A v1.15.0 move needs a separate exact-family decision; v2 beta, + typed-error/status, OTel, GET/CSRF, protocol rollout, and broad migration work belong to a + separate RFC/spike. +13. No product implementation belongs in this RFC PR. ## Type proof @@ -174,7 +204,8 @@ than deepen the contract leak. - `@netscript/plugin`: new optional config reference and builder path; no SDK runtime dependency. - `@netscript/plugin-auth-core`: new `./sdk` export and optional explicit `./sdk/server` convenience export; adds a reviewed SDK dependency. -- Generated declarations must remain package-owned and isolated-declaration compatible. +- Generated declarations must remain package-owned and isolated-declaration compatible, with zero + raw oRPC module specifiers or symbols. - Required implementation evidence: `deno doc --lint`, package audit, publish dry-run, packed/prod consumer check, docs on every new entrypoint, and no `@orpc/*` type in emitted declarations. @@ -184,3 +215,13 @@ than deepen the contract leak. - Whether a server environment credential convenience export ships in the first auth slice. - Whether #451 is rescheduled with this work while remaining independent. - Final public naming refinements that preserve the locked semantics. +- Outer wrapper (preferred) versus immutable per-logical-call memoization for stable-v1 + prepare-once. +- Whether procedure-auth metadata is ratified inside RFC-A or as a dependent decision implemented + through #1350. +- Whether the incoming stable-v1 request-header handler is preset-default or explicit, with absent + headers supported for direct calls either way. +- Whether the stable-v1.15.0 exact-family upgrade precedes or follows the minimal seam. +- For the separate v2 RFC: GET/CSRF law, zero-downtime parallel endpoints versus coordinated + rollout, and whether v2 OTel can replace final injection without violating NetScript span + ownership. diff --git a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/supervisor.md b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/supervisor.md index 2e5861b570..beb60953f9 100644 --- a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/supervisor.md +++ b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/supervisor.md @@ -35,7 +35,12 @@ Written at run start per `workflow/lane-policy.md` § Supervisor identity. ## Handoff State -- Generator work is complete at draft PR #1390 and `status:plan-eval`. -- Reviewable RFC/research commit: `89ae608ea935ba8b2776d55e7cb5a09cc29e2520`. +- Generator RFC authorship completed at draft PR #1390; this exact thread then resumed for the + root-requested post-generator oRPC v2 research amendment. +- Pre-amendment RFC/research commit: `89ae608ea935ba8b2776d55e7cb5a09cc29e2520`; pre-amendment + handoff HEAD: `e78ac0a65f5475ed37152272b16ba7d89deca8c3`. +- The amended RFC is returned to `status:plan-eval` only after focused gates, an explicit-refspec + push, and a structured PR phase comment. - The exact Fable entry point and prohibited mutations are in `final-handoff.md`. -- No evaluator was launched and no external verdict is claimed by this session. +- The amendment is root-requested research, not a formal evaluator verdict. No evaluator was + launched and no external verdict is claimed by this session. diff --git a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/worklog.md b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/worklog.md index 23e0fa5f53..af0ecc4ff6 100644 --- a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/worklog.md +++ b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/worklog.md @@ -25,7 +25,9 @@ future surfaces: - `@netscript/plugin/config`: optional `sdkClients` module reference group. - `@netscript/plugin-auth-core/sdk`: constrained bearer contribution factory. -No new generic transport/plugin/query middleware envelope is authorized. +No new generic transport/plugin/query middleware envelope is authorized. All public and generated +declarations are upstream-major-neutral. Three internal SDK ports isolate procedure metadata, +prepared outbound headers, and transport policy; none is a public export. ### Domain Vocabulary @@ -36,6 +38,9 @@ No new generic transport/plugin/query middleware envelope is authorized. - **Response-cache effect** — `invariant`, `partitioned`, or `direct-only` safety declaration. - **Partition** — synchronous, stable, non-secret full-key discriminator visible in cache tools. - **Transport policy** — SDK-owned discovery/codec/fetch/retry/dedupe/trace/dispatch. +- **Logical call** — one user invocation including all transport retry attempts. +- **Prepared call** — one immutable contributor header/context snapshot reused across those + attempts. ### Composition Law @@ -45,8 +50,10 @@ No new generic transport/plugin/query middleware envelope is authorized. 3. Calls execute contributors sequentially in tuple order with the same snapshot. 4. Contributors never observe accumulated results; valid disjoint patches commute. 5. Tuple order affects only deterministic first-error reporting. -6. Merged contributed headers enter the single native oRPC async header resolver. -7. Transport adds base content type and final client-span trace headers, then dispatches. +6. The prepared-header port runs exactly once per logical call and creates an immutable prepared + call. +7. The transport-policy port receives only that prepared call; each retry reuses byte-equivalent + contributor headers/context, then transport adds base content type and final trace fields. ### Context and Query Law @@ -56,13 +63,24 @@ No new generic transport/plugin/query middleware envelope is authorized. - `partitioned` values add an id-sorted suffix to full keys only. - `direct-only` service keys are absent from generated query/query-utils maps. - No contribution may author query defaults, callbacks, or arbitrary key fragments. +- This law survives upstream majors; official v2 TanStack integration still excludes client context + from query keys. ### Ports and Boundaries -- The RFC composes oRPC's existing async `RPCLink.headers` behavior behind NetScript-owned types. +- Stable v1 supplies the first private adapter; RFC-A does not expose or normatively depend on its + link/header/context/metadata types. +- Internal `ProcedureMetadataPort`, `PreparedOutboundHeadersPort`, and `ClientTransportPolicyPort` + responsibilities are normative; upstream wiring is not. +- Prepare-once is above retries. An outer wrapper is preferred; immutable per-logical-call + memoization is conforming. Direct unmemoized link-header preparation is not. - The internal `ClientLinkPort` is evidence for #451; it is not exposed by this RFC. - `RPCHandlerConfig.plugins` remains the separate server plugin axis. +- `RequestHeadersHandlerPlugin` is only an optional incoming server companion; direct calls may have + no request headers. - Trace propagation is transport-owned; `traceparent`/`tracestate` are reserved. +- oRPC v2 beta, typed-error/status, GET/CSRF, OpenTelemetry, and coordinated protocol migration are + separately owned RFC/spike scope. ### Security and Failure @@ -107,6 +125,7 @@ fluent builders, and global registries. | 1 | Activate run identity and evidence skeleton | identity/path review + git status | run bootstrap artifacts | | 2 | Lock research and author the RFC | source/API citations + type proof + formatting | RFC plus research/design artifacts | | 3 | Prove docs/JSR/GitHub readiness and hand off | docs/RFC/doctrine gates + live PR reconciliation | final artifact updates and `final-handoff.md` | +| 4 | Reconcile root oRPC v2 audit amendment | primary-source audit + repeated docs/PR gates | RFC and every mandatory handoff artifact | ### Deferred Scope @@ -123,24 +142,29 @@ considered complete. ## Progress Log -| Date | Slice | Step | Evidence/result | -| ---------- | ----- | ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------- | -| 2026-08-08 | 1 | authority/identity | Read all requested skills, full harness/RFC/doctrine/profile authorities, relevant debt, and full proposal; verified exact base/session/path/auth. | -| 2026-08-08 | 1 | bootstrap | Created mandatory artifacts, committed `158849031bba78025d0ec16c8361628211fbc4ed`, pushed explicit refspec, opened draft PR #1390. | -| 2026-08-08 | 1 | PR metadata | Applied required labels plus sole `status:research`; no milestone; body references #1348 without closing keyword; posted slice S1 comment. | -| 2026-08-08 | 2 | live board | Re-read #1347–#1353 and #1093/#451/#928/#934/#922/#884, including milestone mapping; no mutation. | -| 2026-08-08 | 2 | public API | Used `deno doc` for SDK/service/plugin/contracts and focused source reads for link/query/metadata/auth/telemetry paths. | -| 2026-08-08 | 2 | dependency | `deps:why` proves live oRPC client; stable report says coherent family is behind to 1.15.0 as of research date. | -| 2026-08-08 | 2 | upstream | Verified official oRPC headers/context/metadata docs and Fetch/W3C/RFC/OWASP primary security sources. | -| 2026-08-08 | 2 | type proof | Scratch Deno proof passes required/optional intersection, named conflicts, 16 accepted, 17 rejected. | -| 2026-08-08 | 2 | design correction | Rejected trace as second consumer; chose locale. Added mandatory cache-effect law after finding query context/key erasure. | -| 2026-08-08 | 2 | RFC | Authored and formatted 1,000+ line decision-complete `rfcs/0000-sdk-client-contributions.md`. | -| 2026-08-08 | 2 | JSR baseline | Four package dry-runs OK; structured doc-lint/private-type baselines and existing plugin audit failure recorded. | -| 2026-08-08 | 3 | doctrine | `deno task arch:check` exits 0; warning-only package debt is pre-existing and remains unwaived. | -| 2026-08-08 | 3 | plan gate | Self-audit covers current state/gap, alternatives, exact surface, laws, failures, migration, slices/issues, and gates; no evaluator verdict claimed. | -| 2026-08-08 | 3 | final docs/type | Re-ran exact-shape type proof, eight-file format check, 102-document links, docs accuracy, focused RFC links, and diff hygiene; all pass. | -| 2026-08-08 | 3 | RFC commit | Committed/pushed `89ae608ea935ba8b2776d55e7cb5a09cc29e2520`; posted structured research and plan summaries. | -| 2026-08-08 | 3 | PR reconciliation | Draft PR has all required labels, sole `status:plan-eval`, no milestone/closing keyword; review-thread gate passes 0/0. | +| Date | Slice | Step | Evidence/result | +| ---------- | ----- | ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| 2026-08-08 | 1 | authority/identity | Read all requested skills, full harness/RFC/doctrine/profile authorities, relevant debt, and full proposal; verified exact base/session/path/auth. | +| 2026-08-08 | 1 | bootstrap | Created mandatory artifacts, committed `158849031bba78025d0ec16c8361628211fbc4ed`, pushed explicit refspec, opened draft PR #1390. | +| 2026-08-08 | 1 | PR metadata | Applied required labels plus sole `status:research`; no milestone; body references #1348 without closing keyword; posted slice S1 comment. | +| 2026-08-08 | 2 | live board | Re-read #1347–#1353 and #1093/#451/#928/#934/#922/#884, including milestone mapping; no mutation. | +| 2026-08-08 | 2 | public API | Used `deno doc` for SDK/service/plugin/contracts and focused source reads for link/query/metadata/auth/telemetry paths. | +| 2026-08-08 | 2 | dependency | `deps:why` proves live oRPC client; stable report says coherent family is behind to 1.15.0 as of research date. | +| 2026-08-08 | 2 | upstream | Verified official oRPC headers/context/metadata docs and Fetch/W3C/RFC/OWASP primary security sources. | +| 2026-08-08 | 2 | type proof | Scratch Deno proof passes required/optional intersection, named conflicts, 16 accepted, 17 rejected. | +| 2026-08-08 | 2 | design correction | Rejected trace as second consumer; chose locale. Added mandatory cache-effect law after finding query context/key erasure. | +| 2026-08-08 | 2 | RFC | Authored and formatted 1,000+ line decision-complete `rfcs/0000-sdk-client-contributions.md`. | +| 2026-08-08 | 2 | JSR baseline | Four package dry-runs OK; structured doc-lint/private-type baselines and existing plugin audit failure recorded. | +| 2026-08-08 | 3 | doctrine | `deno task arch:check` exits 0; warning-only package debt is pre-existing and remains unwaived. | +| 2026-08-08 | 3 | plan gate | Self-audit covers current state/gap, alternatives, exact surface, laws, failures, migration, slices/issues, and gates; no evaluator verdict claimed. | +| 2026-08-08 | 3 | final docs/type | Re-ran exact-shape type proof, eight-file format check, 102-document links, docs accuracy, focused RFC links, and diff hygiene; all pass. | +| 2026-08-08 | 3 | RFC commit | Committed/pushed `89ae608ea935ba8b2776d55e7cb5a09cc29e2520`; posted structured research and plan summaries. | +| 2026-08-08 | 3 | PR reconciliation | Draft PR has all required labels, sole `status:plan-eval`, no milestone/closing keyword; review-thread gate passes 0/0. | +| 2026-08-08 | 4 | audit intake | Read `.llm/tmp/orpc-v2-audit-followup.md` in full (59 lines; recorded SHA-256); no evaluator or rival session launched. | +| 2026-08-08 | 4 | upstream recheck | Official releases/migration/plugin/TanStack/error docs plus beta.25 codec/retry source confirm prerelease v2, protocol incompatibility, changed metadata, incoming-only plugin, excluded context keys, and per-retry header resolution. | +| 2026-08-08 | 4 | repository scope | Focused scan: 91 `@orpc/*` files, 74 excluding test patterns; stable tool reports all seven workspace oRPC dependencies behind to v1.15.0. | +| 2026-08-08 | 4 | design amendment | Locked zero-oRPC public declarations, three internal ports, prepare-once retry law, stable-v1 implementation, and separate v2 RFC/spike gates. | +| 2026-08-08 | 4 | focused validation | Re-ran eight-file format, RFC/repository links, docs accuracy, type proof, doctrine, and diff hygiene; all verdict commands exit 0. | ## Decisions @@ -155,6 +179,10 @@ considered complete. | Keep trace transport-owned. | Client span is created at fetch dispatch; earlier trace header is wrong/overwritten. | `http-client-link.ts`, W3C Trace Context | | Put bearer factory in auth core. | Convention-bearing primitive belongs in core; plugin stays thin. | doctrine 11 | | Keep errors separate from contract errors. | Preparation precedes any server response. | failure taxonomy, #1350 boundary | +| Keep RFC-A upstream-major-neutral. | v1/v2 wire and metadata/retry facilities differ; public seam must survive both. | official v2 migration, doctrine A14 | +| Implement against stable v1 only. | v2 beta is pre-release and coordinated migration spans at least 60 production files. | releases, repo scan, root audit | +| Prepare once above retries. | Direct link headers can resolve per downstream retry and rotate credentials mid-call. | beta.25 codec/retry source | +| Classify incoming headers separately. | Server request-header plugin is optional and absent for direct calls. | official request-header plugin docs | ## Drift @@ -165,6 +193,7 @@ considered complete. | Proposal's trace second consumer conflicts with current client-span injection. | significant design drift | yes | | Proposal omitted cache identity risk of typed auth/locale context. | significant design drift | yes | | Current package doc-lint/JSR baselines contain pre-existing findings. | baseline | yes | +| Original RFC prose treated stable-v1 link headers as the normative lifecycle. | significant design drift | yes | ## Gate Results @@ -182,9 +211,17 @@ considered complete. | Diff hygiene | `git diff --check` | PASS | | PR metadata | live `gh pr view` | PASS: draft/main, required labels, exactly one `status:plan-eval`, milestone null, #1348 reference only | | Review threads | `deno task agentic:review-threads -- --repo rickylabs/netscript --pr 1390 --pretty` | PASS, 0 threads / 0 unanswered | - -Generator gates and PR reconciliation are complete. External Fable/Qwen verdicts remain pending by -owner instruction. +| Audit input | `wc -l` and `sha256sum .llm/tmp/orpc-v2-audit-followup.md` | PASS, 59 lines; SHA-256 `fa8b0ab5cd1afd57b8f6c20036a265fa7c8fb48764f88f97f289c44c0737d3d0` | +| oRPC stable channel | `deno task deps:latest --filter '@orpc/*'` | Seven v1.14.x workspace dependencies behind to stable v1.15.0; evidence only, no dependency mutation | +| oRPC impact scan | focused `rg -l '@orpc/' packages plugins` | 91 reference files; 74 after excluding test paths/name patterns | +| Amendment format | `deno fmt --check` on RFC plus seven mandatory handoff artifacts | PASS, eight files | +| Amendment RFC links | focused internal-doc link checker | PASS, 1 document, 0 broken links/anchors | +| Amendment docs | `deno task docs:links`; `deno task docs:accuracy` | PASS, 102 docs/0 broken; accuracy PASS | +| Amendment type proof | ignored exact-shape Deno probe | PASS | +| Amendment doctrine | `deno task arch:check` | PASS, exit 0; warning-only baseline unchanged | + +The root-requested amendment content gates are complete. Its commit, explicit-refspec push, final PR +reconciliation, and external Fable/Qwen verdicts remain pending at this checkpoint. ## Handoff Notes @@ -196,4 +233,9 @@ External reviewers should attack: inference budget; 4. whether redaction permits any indirect token/partition leakage or source-error reappearance; and 5. whether plugin availability versus explicit activation is sufficiently concrete for #1093 and - generators. + generators; +6. whether the internal outer wrapper or memoized realization best proves prepare-once; +7. whether auth metadata sits inside RFC-A acceptance or a dependent ratification; +8. whether stable-v1.15.0 should precede the seam and incoming request headers should be preset + default; and +9. whether the separate v2 RFC gates GET/CSRF, mixed endpoints, and OTel ownership strongly enough. diff --git a/rfcs/0000-sdk-client-contributions.md b/rfcs/0000-sdk-client-contributions.md index 60509c9104..44b316f38d 100644 --- a/rfcs/0000-sdk-client-contributions.md +++ b/rfcs/0000-sdk-client-contributions.md @@ -20,11 +20,14 @@ serialization, retry, deduplication, tracing, fetch, and transport. Query helper context only when each contribution proves that its response cache is invariant or supplies a synchronous, non-secret partition; otherwise the contributed client is direct-call-only. -The design composes oRPC's existing async `RPCLink.headers` and client-context mechanisms. It does -not expose upstream oRPC types or create a second middleware framework. Bearer credentials in -`@netscript/plugin-auth-core` are the first dogfood consumer. A locale contribution, which owns -`accept-language`, is the required non-auth proof. Trace propagation remains transport-owned because -the final `traceparent` must describe the SDK's client span, not an earlier header callback. +The public protocol and generated declarations are upstream-major-neutral: they contain no oRPC +types, links, plugins, contexts, interceptors, or metadata accessors. NetScript-owned internal ports +translate procedure metadata, prepared outbound headers, and transport policy to the supported +adapter. The first implementation targets stable oRPC v1; an oRPC v2 migration is a separate, +coordinated RFC/spike. Bearer credentials in `@netscript/plugin-auth-core` are the first dogfood +consumer. A locale contribution, which owns `accept-language`, is the required non-auth proof. Trace +propagation remains transport-owned because the final `traceparent` must describe the SDK's client +span, not an earlier header callback. ## Motivation @@ -46,12 +49,23 @@ Current `main` does not justify that width: | [`baseContract`](../packages/contracts/src/application/contract-primitives.ts) does not initialize typed metadata and is annotated as `ReturnType`. | Procedure metadata and the existing error-map erasure need repair, but client preparation errors must not masquerade as server contract errors. | | The lock resolves the oRPC family to 1.14.6, while the repository's stable-channel tool reported 1.15.0 on 2026-08-08. | The implementation must re-run the stable check and move the family coherently; this RFC must depend on public behavior rather than copied private upstream types. | -The repository already contains the needed mechanism. In oRPC 1.14.6, `RPCLink` accepts an async -header resolver whose arguments include client options, procedure path, and input. oRPC's client -context also makes a non-empty context required at call sites, and TanStack Query utilities already -thread that context. The official [RPCLink documentation](https://orpc.dev/docs/client/rpc-link) -shows the same header/context path. NetScript currently hides those capabilities behind a fixed -context and a hardcoded callback. +The repository already contains enough stable-v1 behavior to implement an adapter. In oRPC 1.14.6, +`RPCLink` accepts an async header resolver whose arguments include client options, procedure path, +and input. oRPC's client context also makes a non-empty context required at call sites, and TanStack +Query utilities already thread that context. The official +[v1 RPCLink documentation](https://v1.orpc.dev/docs/client/rpc-link) shows the same header/context +path. NetScript currently hides those capabilities behind a fixed context and a hardcoded callback. +Those upstream facilities are implementation evidence, not the RFC-A public seam. + +A root-requested post-generator audit on 2026-08-08 found that oRPC v2 was still pre-release +(`v2.0.0-beta.26` had already superseded `beta.25`), while `v1.15.0` remained the latest stable +release. The official [v1-to-v2 migration guide](https://v2.orpc.dev/docs/migrations/from-v1) states +that the wire protocol changed and a v1 client cannot communicate with a v2 server. A focused +repository scan found 74 non-test files containing `@orpc/*` references (91 including tests), across +SDK, service, contracts, plugins, telemetry, Fresh/desktop, CLI/scaffold, serialization, OpenAPI, +errors, and query integration. RFC-A therefore MUST NOT smuggle a beta migration into its +implementation. A low-risk, exact-family move from v1.14.x to stable v1.15.0 may precede RFC-A after +a separate upgrade decision; v2 requires its own coordinated migration RFC/spike. ### User problem @@ -81,7 +95,10 @@ This RFC MUST: 5. preserve auth, locale, and arbitrary input/context secrecy in errors and telemetry; 6. keep response caches partitioned when a contributed header can change representation; 7. make contributions statically discoverable but explicitly selected; and -8. retain SDK ownership of the HTTP transport and its observability invariants. +8. retain SDK ownership of the HTTP transport and its observability invariants; +9. keep every public and generated declaration independent of the selected upstream major; and +10. prepare contribution output exactly once per logical call and replay one immutable result across + transport retries. ### Non-goals @@ -93,6 +110,9 @@ This RFC does not: - make client metadata enforce server authorization; - expose a custom transport option (issue [#451](https://github.com/rickylabs/netscript/issues/451) owns that independent decision); +- migrate production to oRPC v2, adopt v2 typed-error/status-map semantics, or replace NetScript's + OpenTelemetry span/injection ownership; +- select GET/POST behavior or CSRF policy through a contribution; - redesign the two existing query-key algebras beyond adding a safe partition suffix; - fix the `baseContract` error-map erasure tracked by [#1350](https://github.com/rickylabs/netscript/issues/1350); or @@ -112,6 +132,12 @@ This RFC does not: credential and is intentionally visible in cache tools. - **Transport policy**: discovery, URL/method selection, codec, retry, dedupe, tracing, `fetch`, streaming, and dispatch. The SDK owns it for `createServiceClient()`. +- **Logical call**: one user-visible procedure invocation, including every transport retry required + to produce its final result. +- **Prepared call**: the logical call plus one immutable, validated contributor-header record. Every + retry receives the same prepared contributor output and context snapshot. +- **Adapter port**: a NetScript-owned, non-exported structural boundary between RFC-A semantics and + the selected transport/contract implementation. Upstream-specific adapters implement these ports. ## Guide-level explanation @@ -272,9 +298,9 @@ runtime; it is not a property containing `undefined`. ### Async and server-side sources -`prepare` and `resolveCredential` may be async and are invoked once for every transport attempt that -represents a new logical call. They are never invoked at module import or client construction. An -application may close over a concurrency-safe rotating credential source: +`prepare` and `resolveCredential` may be async and are invoked exactly once per logical call, before +any transport retry loop. They are never invoked at module import, client construction, or again for +a retry attempt. An application may close over a concurrency-safe rotating credential source: ```ts const bearer = createBearerSdkClientContribution({ @@ -294,24 +320,25 @@ cookies. The framework does not guess the runtime from globals. This RFC spans four existing archetypes and no new package: -| Package/surface | Archetype | Responsibility | -| -------------------------------------------------- | ----------------------- | ------------------------------------------------------------------------------------------- | -| `@netscript/contracts` | Public DSL/builder | Own the cross-runtime procedure metadata vocabulary. | -| `@netscript/sdk/ports` and `@netscript/sdk/client` | Public DSL/builder | Own upstream-free descriptor types, type algebra, preparation errors, and the HTTP adapter. | -| `@netscript/sdk` | Public preset | Preserve tuples through `defineServices()` and expose one-call ergonomics. | -| `@netscript/plugin/config` | Plugin protocol/config | Carry static module references without importing SDK runtime types. | -| `@netscript/plugin-auth-core/sdk` | Plugin core/integration | Own the convention-bearing bearer contribution and security policy. | -| `plugins/auth` | Thin plugin delivery | Declare the module reference and generated/scaffold wiring only. | -| CLI generators | Tooling | Generate explicit imports and literal tuples; validate plugin references. | +| Package/surface | Archetype | Responsibility | +| -------------------------------------------------- | ----------------------- | ------------------------------------------------------------------------------------------------------ | +| `@netscript/contracts` | Public DSL/builder | Own the cross-runtime procedure metadata vocabulary. | +| `@netscript/sdk/ports` and `@netscript/sdk/client` | Public DSL/builder | Own upstream-free descriptor types, type algebra, and preparation errors. | +| `@netscript/sdk` | Public preset | Preserve tuples through `defineServices()`, expose one-call ergonomics, and own private adapter ports. | +| `@netscript/plugin/config` | Plugin protocol/config | Carry static module references without importing SDK runtime types. | +| `@netscript/plugin-auth-core/sdk` | Plugin core/integration | Own the convention-bearing bearer contribution and security policy. | +| `plugins/auth` | Thin plugin delivery | Declare the module reference and generated/scaffold wiring only. | +| CLI generators | Tooling | Generate explicit imports and literal tuples; validate plugin references. | This follows the doctrine's extension-axis law: a cross-package extension is named, registered, deterministic, and duplicate-rejecting. It also follows the public-surface law: NetScript owns the types and does not re-export `RPCLinkOptions`, `ClientOptions`, `StandardHeaders`, upstream plugin -types, or interceptor types. +types, interceptor types, upstream context, or upstream metadata accessors. The three internal +adapter ports below are package-private and do not enlarge the JSR surface. ### Procedure metadata -`@netscript/contracts` adds the following root exports and initializes `baseContract` with them: +`@netscript/contracts` adds the following root exports: ```ts export type NetScriptAuthenticationRequirement = @@ -324,19 +351,42 @@ export interface NetScriptProcedureMeta { readonly authentication?: NetScriptAuthenticationRequirement; }; } +``` + +The normative semantic requirement is that `baseContract` and every derived contract accept +`NetScriptProcedureMeta`, preserve it through the publishable contract declaration, and expose it to +the SDK metadata port. Missing metadata normalizes to `{}`. The implementation MUST use an explicit +publishable annotation that preserves both the concrete common error map and +`NetScriptProcedureMeta`; it MUST NOT retain the erasing `ReturnType` annotation. +The exact error-map repair belongs to #1350, but the metadata and error work must land coherently so +one does not re-erase the other. + +How an upstream adapter stores or reads this semantic metadata is non-normative. For illustration, +the supported v1 adapter can initialize its private builder with v1's typed metadata facility: -const contractWithMeta = oc.$meta({}); -export const baseContract = contractWithMeta.errors(commonErrorMap); +```ts +// packages/contracts internal v1 adapter; never emitted in NetScript public declarations +const v1ContractBuilder = oc.$meta({}); ``` -The implementation MUST use an explicit publishable annotation that preserves both the concrete -common error map and `NetScriptProcedureMeta`; it MUST NOT retain the erasing -`ReturnType` annotation. The exact error-map repair belongs to #1350, but the -metadata and error work must land coherently so one does not re-erase the other. +A later v2 spike would instead use v2 metadata plugins and synthesize the same NetScript descriptor: -`ContractProcedureMetadata` in `@netscript/sdk/ports` gains a package-owned `meta` member and the -SDK normalizes missing metadata to `{}`. This mirrors the public `procedure['~orpc'].meta` field -documented by [oRPC metadata](https://orpc.dev/docs/metadata) without exporting an upstream type. +```ts +// hypothetical internal v2 adapter; not part of RFC-A implementation +const [accessMeta, readAccessMeta] = defineMeta( + 'netscript.access', + (incoming: NetScriptProcedureMeta['access']) => incoming, +); + +const descriptor: SdkClientProcedureDescriptor = { + path, + meta: { access: readAccessMeta(procedure) }, +}; +``` + +This follows the official +[v2 migration from `.$meta` to `defineMeta`](https://v2.orpc.dev/docs/migrations/from-v1#meta-replaced-by-meta-plugins). +Neither adapter form appears in the contribution protocol or generated public source. ### Public contribution contract @@ -413,6 +463,64 @@ export interface SdkClientContribution< } ``` +### Internal adapter ports + +The implementation MUST introduce exactly three NetScript-owned internal adapter responsibilities. +The following structural contract is normative inside `@netscript/sdk`, but the names are not public +exports and MUST NOT appear in `deno doc` or generated JSR declarations: + +```ts +interface SdkClientLogicalCall { + readonly context: Readonly; + readonly procedurePath: readonly string[]; + readonly procedureNode: unknown; + readonly transport: SdkClientTransportDescriptor; + readonly input: unknown; + readonly signal?: AbortSignal; +} + +interface PreparedOutboundHeaders { + readonly values: Readonly>; +} + +interface PreparedSdkClientCall { + readonly call: SdkClientLogicalCall; + readonly procedure: SdkClientProcedureDescriptor; + readonly contributedHeaders: PreparedOutboundHeaders; +} + +interface PreparedOutboundHeadersPort { + prepare( + call: SdkClientLogicalCall, + ): Promise>; +} + +interface ProcedureMetadataPort { + describe( + procedureNode: unknown, + procedurePath: readonly string[], + ): SdkClientProcedureDescriptor; +} + +interface ClientTransportPolicyPort { + dispatch( + call: PreparedSdkClientCall, + ): Promise; +} +``` + +`ProcedureMetadataPort` is the only component allowed to interpret an upstream procedure node. +`PreparedOutboundHeadersPort` performs tuple composition and validation exactly once per logical +call. `ClientTransportPolicyPort` owns every attempt, retry, encoding, trace, and dispatch action +and MUST accept already prepared output; it MUST NOT invoke contributors. The supported v1 adapter +and a future v2 adapter may have different private wiring, but both must satisfy these same port +semantics. + +The prepared call retains one context/snapshot identity and one canonical lower-case header record. +An adapter creates a fresh transport header container for each attempt, but the contributor-owned +entries and the preparation-context projection are byte-equivalent across attempts. Trace fields or +other transport-owned fields are added only after this invariant is established. + `defineSdkClientContribution()(descriptor)` preserves `id`, the context declaration, header keys, and cache mode as literals. Its parameter applies these static checks: @@ -547,6 +655,11 @@ The cache suffix is appended only to full keys. Resource/procedure prefixes and invalidation helpers remain unchanged. A conformance test MUST prove that two auth partitions with identical input cannot observe each other's server or TanStack cached data. +This rule is upstream-major-neutral and cannot be removed during a transport migration. The official +[oRPC v2 TanStack integration](https://v2.orpc.dev/docs/integrations/tanstack-query#client-context) +still excludes client context from query keys, so neither stable v1 nor a future v2 adapter can make +client context itself a safe cache partition. + This narrow cache-effect declaration is not a query contribution. It cannot set stale times, retry, invalidation callbacks, query functions, or arbitrary key fragments. @@ -563,13 +676,15 @@ Construction performs these steps in tuple order: At call time: 1. resolve the service origin and procedure node; -2. create one read-only preparation snapshot; -3. invoke contributors sequentially in tuple order with that same snapshot; -4. after each await, validate that the patch is a plain record, every header was declared, values +2. use `ProcedureMetadataPort` to create the NetScript procedure descriptor; +3. create one read-only logical-call preparation snapshot; +4. invoke contributors sequentially in tuple order with that same snapshot; +5. after each await, validate that the patch is a plain record, every header was declared, values are valid strings without CR/LF, and the call has not been aborted; -5. merge the disjoint patches into a new record; -6. pass that record to the single native oRPC header resolver; and -7. let the SDK transport encode, trace, retry/dedupe, fetch, and decode the call. +6. merge the disjoint patches into a new immutable lower-case record; +7. construct one `PreparedSdkClientCall`; and +8. pass only that prepared call to `ClientTransportPolicyPort`, which may encode, trace, + retry/dedupe, fetch, and decode without invoking preparation again. Contributions never see accumulated headers or another contribution's result. Valid contributions therefore commute: tuple order cannot change a successful request. Order determines only which @@ -606,10 +721,27 @@ trace fields after contribution validation. ### Async context, retries, and cancellation -Preparation runs once per logical client call, before oRPC retry machinery. Retries reuse the -prepared result for that call. This avoids fetching a different credential or locale halfway through -one retry sequence. Credential refresh after a `401` requires a future explicit replay policy; an -interceptor hidden in an auth contribution would make side-effect replay unsafe. +Preparation runs exactly once per logical client call, semantically above the adapter's retry loop. +Retries reuse the same immutable `PreparedSdkClientCall`. This avoids fetching a different +credential or locale halfway through one retry sequence. Credential refresh after a `401` requires a +future explicit replay policy; an interceptor hidden in an auth contribution would make side-effect +replay unsafe. + +The adapter MUST realize prepare-once with either an outer logical-call wrapper (preferred because +the lifecycle is explicit) or an immutable per-logical-call memo shared by every attempt. Wiring +`prepare()` directly to an upstream link-header callback is non-conforming unless that callback +reads only such a memo. Official oRPC `v2.0.0-beta.25` source resolves link headers during input +encoding, while its retry plugin invokes the downstream chain again per attempt; a direct async +header callback therefore runs once per retry, not once per logical call. The supported v1 adapter +must be tested rather than assumed to differ. + +A mandatory conformance fixture forces at least one retry and proves all of the following: + +- contributor preparation count is exactly `1`; +- each attempt receives a freshly materialized transport header container; +- the canonical contributor-header bytes are identical on every attempt; and +- the logical-call context/procedure projection observed by the adapter is the same immutable + snapshot on every attempt. If the call signal is already aborted, no contributor runs. If it aborts during an async resolver, the SDK stops awaiting, does not dispatch, and rejects with the platform abort reason. A resolver @@ -623,9 +755,11 @@ must not mutate them. ### Transport ownership and oRPC alignment -Version 1 contributes only the existing oRPC `RPCLink.headers` capability. The adapter supplies one -composed async resolver. This is the thinnest mapping to an upstream public seam and preserves -NetScript's ability to replace oRPC without changing public contribution types. +Version 1 contributes only prepared outbound header values and typed per-call context. It does not +contribute an upstream callback. The initial stable-v1 adapter may map an already prepared record +into the native link-header facility, provided that preparation occurs above retries or through the +specified per-call memo. A future v2 adapter may use different private wiring. These are +non-normative adapter choices; the three NetScript ports and prepare-once behavior are normative. The SDK remains the sole owner of: @@ -639,7 +773,8 @@ The SDK remains the sole owner of: Accordingly the descriptor has no `fetch`, `link`, `plugins`, `interceptors`, `clientInterceptors`, `adapterInterceptors`, serializer, retry, or error-map fields. The transport consolidation issue [#1351](https://github.com/rickylabs/netscript/issues/1351) may refactor those internals and update -oRPC, but it MUST keep one SDK-owned policy path. +oRPC within stable v1, preferably to the exact v1.15.0 family after a separate upgrade decision, but +it MUST keep one SDK-owned policy path. It MUST NOT migrate production to v2 as part of RFC-A. Issue #451 may separately expose a custom transport. If accepted, it MUST adapt the existing package-owned `ClientLinkPort`, declare whether it accepts prepared request headers, and reject a @@ -654,6 +789,28 @@ reserves `traceparent` and `tracestate`. The W3C [Trace Context recommendation](https://www.w3.org/TR/trace-context/) also requires careful mutation and calls out correlation/privacy risk. +#### Optional incoming server companion + +oRPC v2's [`RequestHeadersHandlerPlugin`](https://v2.orpc.dev/docs/plugins/request-headers) is an +optional incoming server companion, not the RFC-A extension seam. It is the renamed v1 +request-header handler facility and makes request headers available to handler context. It does not +provide outbound contribution ownership, duplicate/conflict policy, async credential resolution, +redaction, or cache partitioning. When a procedure is called directly without an HTTP request, its +request-header context is optional and may be absent; server middleware MUST define direct-call +behavior rather than pretending an outbound client contribution exists. + +Whether a stable-v1 server installs the corresponding incoming plugin by default is a service-preset +decision for implementation review. Either choice MUST preserve direct-call tests and MUST NOT make +RFC-A client metadata enforce server authorization. + +#### Boundaries reserved for the v2 migration + +RFC-A does not adopt v2's typed-error/status-map redesign or its `@orpc/opentelemetry` integration. +It also does not change HTTP method selection: transport owns GET/POST, and any later v2 adapter +that enables GET must prove an explicit CSRF law. NetScript continues to own its client-span +topology and final trace injection unless the separate v2 RFC proves that upstream instrumentation +can replace them without missing spans or emitting duplicates. + ### Error and failure model The SDK exports one package-owned error and its redacted diagnostic shape: @@ -846,28 +1003,55 @@ Generated projects change only when the user selects a contributor. Because this RFC changes public and publish surfaces, implementation packages must bump versions according to the release plan and pass JSR isolated-declaration gates. No implementation is allowed -to publish an `@orpc/*` type in a generated `.d.ts`/JSR declaration. +to publish an `@orpc/*` type in a generated `.d.ts`/JSR declaration. More strongly, the public SDK +protocol and all generated public declarations MUST contain zero raw oRPC symbols: no upstream +module specifier, link, plugin, context, interceptor, metadata accessor, or structural alias whose +meaning depends on an upstream major. NetScript-owned public types may be implemented by an +upstream-specific private adapter but cannot inherit its identity. + +The first implementation's compatibility target is the supported stable-v1 adapter. A later v2 spike +must run the same contribution conformance suite against its adapter before any migration RFC can +propose production adoption. Passing RFC-A on stable v1 does not imply v2 compatibility, and adding +a v2 adapter must not change the contribution protocol major. ### Staged implementation plan and issue decomposition Implementation remains outside this RFC PR. -| Stage | Existing owner | Scope and exit condition | -| -------------------------- | ----------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| 0. Ratify | [#1348](https://github.com/rickylabs/netscript/issues/1348) | Accept this RFC, settle safe FCP questions, and reconcile child issue bodies. | -| 1. Contract/type repair | [#1350](https://github.com/rickylabs/netscript/issues/1350) | Preserve the concrete base error map and initialize/export `NetScriptProcedureMeta`; type fixtures prove both. | -| 2. Minimal client seam | [#1349](https://github.com/rickylabs/netscript/issues/1349) | Add descriptor/helper, tuple algebra, context-generic client/query surfaces, native header composition, cache-effect handling, and failures. Do not expose upstream callback arrays. | -| 3. Transport consolidation | [#1351](https://github.com/rickylabs/netscript/issues/1351) | Recheck stable oRPC, update the family coherently, keep one fetch/retry/dedupe/trace path, and deprecate current no-op options. | -| 4. Auth dogfood | [#1352](https://github.com/rickylabs/netscript/issues/1352) | Ship the auth-core bearer factory, access metadata behavior, redaction, cache partition/direct-only modes, manifest reference, docs, and scaffold choice. | -| 5. Trace ownership proof | [#1353](https://github.com/rickylabs/netscript/issues/1353) | Re-scope from “trace contribution” to prove the transport retains the only final trace injection and rejects contributor ownership of trace headers. | -| 6. Non-auth proof | new child after RFC acceptance | Ship/test locale contribution, partitioned keys, header conflicts, and generated use. Do not file during this RFC run. | -| 7. Generic discovery | [#1093](https://github.com/rickylabs/netscript/issues/1093) | Discover third-party module references without hardcoded factories; generated selection remains explicit. | +| Stage | Existing owner | Scope and exit condition | +| ------------------------------ | ----------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| 0. Ratify | [#1348](https://github.com/rickylabs/netscript/issues/1348) | Accept this RFC, settle safe FCP questions, and reconcile child issue bodies. | +| 1. Contract/type repair | [#1350](https://github.com/rickylabs/netscript/issues/1350) | Preserve the concrete base error map and initialize/export `NetScriptProcedureMeta`; type fixtures prove both. | +| 2. Minimal client seam | [#1349](https://github.com/rickylabs/netscript/issues/1349) | Add descriptor/helper, tuple algebra, context-generic client/query surfaces, the three internal ports, prepare-once stable-v1 composition, cache-effect handling, and failures. Do not expose upstream callback arrays. | +| 3. Transport consolidation | [#1351](https://github.com/rickylabs/netscript/issues/1351) | Decide separately whether to move the exact oRPC v1 family to stable v1.15.0, keep one fetch/retry/dedupe/trace path, prove prepare-once across retry, and deprecate current no-op options. No v2 migration. | +| 4. Auth dogfood | [#1352](https://github.com/rickylabs/netscript/issues/1352) | Ship the auth-core bearer factory, access metadata behavior, redaction, cache partition/direct-only modes, manifest reference, docs, and scaffold choice. | +| 5. Trace ownership proof | [#1353](https://github.com/rickylabs/netscript/issues/1353) | Re-scope from “trace contribution” to prove the transport retains the only final trace injection and rejects contributor ownership of trace headers. | +| 6. Non-auth proof | new child after RFC acceptance | Ship/test locale contribution, partitioned keys, header conflicts, and generated use. Do not file during this RFC run. | +| 7. Generic discovery | [#1093](https://github.com/rickylabs/netscript/issues/1093) | Discover third-party module references without hardcoded factories; generated selection remains explicit. | +| 8. oRPC v2 migration RFC/spike | new owner after RFC-A review; do not file in this run | Wait for stable unless the owner explicitly accepts beta; prove a complete, coordinated adapter migration independently of RFC-A. | Issue #451 remains the sole future owner of custom links. #928 and #934 consume aligned protocol and metadata vocabulary but are not prerequisites for the header seam. The org-aware policy work in [#884](https://github.com/rickylabs/netscript/issues/884) may later add a tenant context/header contribution, but server authorization and tenant validation remain separate. +The separate v2 RFC/spike must, at minimum, gate all of the following before production adoption: + +- wait for the stable dist-tag unless the owner explicitly accepts beta risk, and pin the entire + oRPC package family to one exact version; +- use a coordinated client/server rollout or parallel versioned endpoints because the protocols are + incompatible; explicitly decide whether zero-downtime mixed-version service is required; +- prove route, metadata, OpenAPI, and Scalar output parity; +- prove typed-error semantics and HTTP status-map parity without folding the migration into #1350; +- audit middleware execution counts now that v2 removes automatic deduplication; +- define the GET/POST/CSRF law; +- prove OpenTelemetry topology and absence of double spans before changing final injection + ownership; +- prove Fresh/desktop serializer parity and SSE/stream lifecycle behavior; +- re-run query-key/cache-partition safety because v2 still excludes client context from keys; +- pass the Deno/browser/server matrix, package checks, full CLI/scaffold E2E, documentation + snippets, and publish dry-run. + ### Conformance and fitness gates An implementation is not complete until all applicable gates pass. @@ -882,7 +1066,8 @@ An implementation is not complete until all applicable gates pass. preserve the per-service context; - `direct-only` service keys are absent from query/query-utils mapped types; - server-defined error inference remains exact after metadata initialization; and -- public declarations contain no upstream oRPC type. +- public and generated declarations contain zero raw oRPC module specifiers or symbols, including + links, plugins, contexts, interceptors, and metadata accessors. #### Runtime gates @@ -890,12 +1075,21 @@ An implementation is not complete until all applicable gates pass. - duplicate validation repeated through `unknown`/JavaScript input; - undeclared, mixed-case, forbidden, CR/LF, non-string, and duplicate headers rejected; - base `Content-Type` and final trace fields cannot be overwritten; -- a retry reuses one prepared result; +- a forced retry records preparation count `1` and byte-equivalent prepared contributor + headers/context on every attempt; - locale and two auth partitions cannot share cached data, while prefix invalidation still works; - direct-only services have no runtime query/query-utils property; and - every error/log/span snapshot excludes header values, input, context, partitions' source values, source messages, tokens, and session ids. +#### Adapter compatibility gates + +- the supported stable-v1 adapter passes the entire contribution conformance suite; +- its upstream link-header callback, if used, consumes only the already prepared per-call record; +- the package declaration graph and generated client declarations pass the zero-oRPC-symbol scan; +- a future v2 spike adapter must pass the same suite before its migration RFC can enter FCP; and +- v2 typed-error/status-map and OpenTelemetry migration tests remain outside RFC-A. + #### Plugin/generated gates - a synthetic third-party manifest contributes a module/export without a core edit; @@ -925,6 +1119,8 @@ Implementation updates must cover: - plugin manifest/config builder documentation; - generated service-client templates and embedded CLI assets; - query partition visibility, direct-only behavior, and cache invalidation; +- upstream-major neutrality, the private adapter boundary, and prepare-once retry behavior; +- the optional incoming request-header companion and direct-call absence behavior; - CORS/preflight, cleartext bearer, cookie, redirect, and retry limitations; and - migration notes for manual header wrappers and deprecated `port`/`timeout` fields. @@ -951,9 +1147,11 @@ environment-derived secret. ### Why this boundary Headers plus typed per-call context are the smallest seam proven by two different consumers. They -map directly to an existing public oRPC callback, can be represented without upstream types, and do -not grant plugins transport control. The cache-effect field is not another behavior hook; it is the -minimum declaration needed to keep existing query surfaces safe. +map through three narrow NetScript-owned ports, can be represented without upstream types, and do +not grant plugins transport control. Stable v1 supplies a viable first adapter, while the same +semantic boundary survives v2's different metadata and retry facilities. The cache-effect field is +not another behavior hook; it is the minimum declaration needed to keep existing query surfaces +safe. ### Rejected: the starting “one envelope for everything” proposal @@ -1030,12 +1228,27 @@ custom-link design gets its own breaking assessment. ## Prior art -- oRPC's [RPCLink](https://orpc.dev/docs/client/rpc-link) provides async headers from typed client - context and exposes path/input to the callback. This RFC composes that capability once. -- oRPC [metadata](https://orpc.dev/docs/metadata) initializes a typed metadata vocabulary with - `$meta()` and exposes it on procedures. NetScript owns the narrower cross-package type. -- oRPC's TanStack integration already requires non-empty client context in query options. NetScript - currently erases it; this RFC restores it without exposing upstream utility types. +- Stable oRPC v1's [RPCLink](https://v1.orpc.dev/docs/client/rpc-link) provides async headers from + typed client context and exposes path/input to the callback. It is evidence for the initial + private adapter, not the RFC-A public protocol. +- The official [v1-to-v2 migration guide](https://v2.orpc.dev/docs/migrations/from-v1) documents the + incompatible wire protocol, metadata-plugin replacement for `.$meta`, middleware execution change, + error/status split, GET/CSRF change, and OpenTelemetry package migration. These are why RFC-A owns + semantic ports rather than an upstream-major shape. +- oRPC v2's [`RequestHeadersHandlerPlugin`](https://v2.orpc.dev/docs/plugins/request-headers) is an + incoming, optional handler companion; direct calls can have no request headers. It is not outbound + contribution composition. +- oRPC v2's + [TanStack integration](https://v2.orpc.dev/docs/integrations/tanstack-query#client-context) + explicitly excludes client context from query keys, preserving RFC-A's partition/direct-only law. +- In oRPC `v2.0.0-beta.25`, the + [standard link codec](https://github.com/middleapi/orpc/blob/v2.0.0-beta.25/packages/client/src/adapters/standard/rpc-link-codec.ts) + resolves headers during encoding and the + [retry plugin](https://github.com/middleapi/orpc/blob/v2.0.0-beta.25/packages/client/src/plugins/retry.ts) + invokes downstream per attempt. This proves that direct link-header preparation is not + prepare-once. +- Official [oRPC releases](https://github.com/middleapi/orpc/releases) mark v2 beta releases as + pre-release and v1.15.0 as the latest stable release as of the audit date. - The WHATWG [Fetch Standard](https://fetch.spec.whatwg.org/#forbidden-request-header) defines request-header ownership that browser code cannot override; runtime validation follows it. - W3C [Trace Context](https://www.w3.org/TR/trace-context/) explains why trace headers have @@ -1045,7 +1258,8 @@ custom-link design gets its own breaking assessment. ## Unresolved questions -These are safe for discussion/FCP because they do not change the extension law: +These are safe for discussion/FCP because the upstream-neutral extension law, prepare-once +invariant, and separate-v2 boundary remain fixed: 1. Should the first implementation reserve exactly 16 contributions, or raise the ceiling if CI type fixtures demonstrate equal cost? It must not ship below 16. @@ -1056,10 +1270,31 @@ These are safe for discussion/FCP because they do not change the extension law: exposes nor requires a custom link. 4. Maintainers may refine public names (`responseCache`, `direct-only`, or the access enum) during FCP while preserving the specified semantics and defaults. +5. Should the stable-v1 adapter use an outer logical-call wrapper (the RFC's preference) or + immutable per-logical-call memoization? Either choice must pass preparation-count `1` and + byte-equivalent retry fixtures; direct unmemoized link-header preparation is not allowed. +6. Should the semantic procedure-auth metadata requirement be accepted inside RFC-A and implemented + through #1350, as written, or ratified in a dependent mini-RFC? The public metadata vocabulary + and upstream-neutral metadata port are required before auth dogfood can ship. +7. Does the owner want the optional stable-v1 incoming request-header handler installed by default + in service presets, or explicitly selected? Direct calls must continue to tolerate absent request + headers under an explicit server policy. +8. Should the separately reviewed stable-v1.15.0 exact-family upgrade precede the minimal client + seam, or should RFC-A first implement against the current v1.14.x family? RFC-A supports either + stable-v1 baseline and does not authorize v2. +9. For the separate v2 migration RFC, must production support zero-downtime mixed-version clients + via parallel endpoints, or is a coordinated atomic client/server rollout acceptable? +10. Does Fable agree that GET enablement and its CSRF law belong exclusively to the transport/v2 + migration RFC rather than RFC-A contributions? +11. Can v2 OpenTelemetry instrumentation ever replace NetScript's final trace injection without + violating NetScript span ownership or creating double spans? This is a v2-spike proof + obligation, not an RFC-A implementation choice. The following are not open: duplicate rejection, order independence, per-call async preparation, -reserved trace ownership, no upstream callback arrays, explicit plugin selection, cache partition -safety, and separation from contract-defined errors. +exactly-once preparation per logical call, reserved trace ownership, zero upstream types/symbols in +public and generated declarations, no upstream callback arrays, explicit plugin selection, cache +partition/direct-only safety, separation from contract-defined errors, and no production v2 beta +migration in RFC-A. ## Future possibilities @@ -1072,3 +1307,5 @@ safety, and separation from contract-defined errors. contribution protocol. - Additional `NetScriptProcedureMeta` fields for gateway and org-aware policy, governed by their owning RFCs. +- A separately ratified oRPC v2 adapter/migration after its compatibility, rollout, error, + telemetry, serializer, streaming, cache, E2E, and publish gates pass. From 7be129d8037c9a4807e6101d62db827e3ff82a70 Mon Sep 17 00:00:00 2001 From: Rickylabs Date: Sat, 8 Aug 2026 19:59:39 +0200 Subject: [PATCH 05/12] docs(harness): hand off oRPC audit amendment --- .../context-pack.md | 7 +- .../final-handoff.md | 120 ++++++++++++------ .../supervisor.md | 1 + .../worklog.md | 7 +- 4 files changed, 93 insertions(+), 42 deletions(-) diff --git a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/context-pack.md b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/context-pack.md index d2340e58dd..118486d80c 100644 --- a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/context-pack.md +++ b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/context-pack.md @@ -82,7 +82,7 @@ migration. This amendment is not an evaluator verdict. No product source is chan | Audit amendment evidence | pass | 59-line input hashed; 91/74 file scan; seven v1 dependencies behind to 1.15.0 | | Audit amendment gates | pass | format, links, accuracy, type proof, doctrine, and diff hygiene | | Pre-amendment PR reconciliation | pass | draft, required labels, sole `status:plan-eval`, no milestone/closing keyword | -| Amendment PR reconciliation | pending | restore sole `status:plan-eval` after explicit-refspec push | +| Amendment PR reconciliation | external record | final pushed HEAD and sole `status:plan-eval` are recorded in the phase comment | ## JSR Consequences @@ -126,5 +126,6 @@ milestones. Findings should cite RFC headings and classify blocking versus safe - Bootstrap: `158849031bba78025d0ec16c8361628211fbc4ed`. - RFC/research: `89ae608ea935ba8b2776d55e7cb5a09cc29e2520`. - Handoff baseline: `e78ac0a65f5475ed37152272b16ba7d89deca8c3`. -- The audit-amendment commit and per-slice PR comment complete the V3 commit record; its SHA is - recorded in the PR comment because an artifact cannot contain its own commit id. +- Audit amendment: `7a0d398087a6608ff1a55bb9fe4c47158edb72a7`. +- The handoff-only commit and per-slice PR comment complete the V3 commit record; the PR comment + records the final pushed HEAD because an artifact cannot contain its own commit id. diff --git a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/final-handoff.md b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/final-handoff.md index 8a8c337b36..02a554790e 100644 --- a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/final-handoff.md +++ b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/final-handoff.md @@ -7,21 +7,24 @@ | Draft PR | `https://github.com/rickylabs/netscript/pull/1390` (#1390) | | Branch | `docs/rfc-sdk-client-contribution` | | Base | `origin/main` at `fac9e339042c5394bf882311657d8981d353a1c3` | -| Reviewable RFC HEAD | `89ae608ea935ba8b2776d55e7cb5a09cc29e2520` | +| Reviewable RFC HEAD | `7a0d398087a6608ff1a55bb9fe4c47158edb72a7` | | RFC | `rfcs/0000-sdk-client-contributions.md` (`0000`, Draft) | | Run dir | `.llm/runs/docs-rfc-sdk-client-contribution--rfc/` | | PR phase | `status:plan-eval` | -`89ae608ea935ba8b2776d55e7cb5a09cc29e2520` is the exact substantive RFC/research commit reviewed by -the generator gates. The commit containing this handoff changes run metadata only; its pushed SHA is -recorded in the S3 PR comment so the handoff does not pretend it can contain its own Git object id. +`7a0d398087a6608ff1a55bb9fe4c47158edb72a7` is the exact substantive amended RFC/research commit +reviewed by the generator gates. The commit containing this handoff changes run metadata only; its +pushed SHA is recorded in the amendment PR comment so the handoff does not pretend it can contain +its own Git object id. ## Outcome The carried-in Fable proposal was challenged rather than copied. The RFC ratifies a narrow, -package-owned request-header preparation axis over oRPC's existing async headers/context seam. It -does not authorize a generic client middleware, raw-link, transport, query-policy, error-map, or -server-plugin framework. +package-owned request-header preparation axis behind three NetScript internal ports. The root's +post-generator oRPC v2 audit was reconciled as research, not an evaluator verdict. RFC-A is now +normatively upstream-major-neutral, implements against stable v1, and leaves the coordinated v2 +migration to a separate RFC/spike. It does not authorize a generic client middleware, raw-link, +transport, query-policy, error-map, or server-plugin framework. ## Decisions Made @@ -50,10 +53,22 @@ server-plugin framework. 10. Omitted contributions preserve current context, headers, query keys, and mapped result keys. Existing generic call sites retain defaults; current no-op `port`/`timeout` fields are deprecated but not removed by this RFC. +11. Public and generated declarations contain zero raw oRPC types, links, plugins, contexts, + interceptors, metadata accessors, or upstream-major aliases. Package-private ports own procedure + metadata, prepared outbound headers, and transport policy. +12. Contribution preparation runs exactly once per logical call above retries. Every attempt + receives byte-equivalent immutable contributor headers/context; direct unmemoized link-header + preparation is non-conforming. +13. `RequestHeadersHandlerPlugin` is only an optional incoming server companion and may have no + headers on direct calls. It does not implement outbound composition, ownership, redaction, or + cache partitioning. +14. RFC-A does not migrate to oRPC v2 beta or adopt v2 error/status, GET/CSRF, or OTel semantics. A + separate v1.15.0 exact-family upgrade may be considered; the broad v2 migration requires its own + RFC/spike and coordinated rollout. ## FCP-Safe Unresolved Questions -Only these questions remain open: +These implementation/sequencing questions remain open without changing the locked extension law: 1. Raise the 16-contribution ceiling if CI type evidence supports it; do not ship below 16. 2. Ship an explicit server-only environment credential helper in the first auth slice or keep it as @@ -61,27 +76,46 @@ Only these questions remain open: 3. Schedule independent custom-link issue #451 alongside implementation or later. 4. Refine public names during FCP without changing defaults, ownership, cache safety, or composition semantics. - -Duplicate rejection, order independence, per-call async preparation, reserved trace ownership, no -upstream callback arrays, explicit activation, cache safety, and separation from contract-defined -errors are not open. +5. Use the preferred outer logical-call wrapper or immutable per-call memoization for prepare-once; + either must pass count `1` and byte-equivalent retry fixtures. +6. Ratify procedure-auth metadata inside RFC-A/#1350 or in a dependent mini-RFC; it must exist + before auth dogfood ships. +7. Install the stable-v1 incoming request-header handler by default in service presets or require + explicit selection; direct calls must tolerate absence under an explicit policy. +8. Upgrade the exact oRPC family to stable v1.15.0 before RFC-A implementation or implement first on + the current v1.14.x baseline. +9. In the separate v2 migration, require zero-downtime parallel endpoints or permit a coordinated + atomic client/server rollout. +10. Confirm that GET enablement and its CSRF law remain transport/v2-migration scope. +11. Determine whether v2 OTel can replace final injection without violating NetScript span ownership + or producing double spans. + +Duplicate rejection, order independence, exactly-once per-logical-call preparation, reserved trace +ownership, zero raw oRPC symbols in public/generated declarations, no upstream callback arrays, +explicit activation, cache safety, separation from contract-defined errors, and no production v2 +beta migration in RFC-A are not open. ## Validation Evidence -| Gate | Result | -| ------------------------ | ------------------------------------------------------------------------------------------------------- | -| Exact base/merge-base | PASS at `fac9e339042c5394bf882311657d8981d353a1c3` | -| RFC/harness formatting | PASS, eight tracked Markdown files checked | -| Focused RFC links | PASS, 1 document, 0 broken links/anchors | -| Repository docs links | PASS, 102 documents, 0 broken links/anchors | -| Docs accuracy | PASS | -| Exact-shape type proof | PASS; required/optional context, conflicts, 16 accepted, 17 rejected | -| Doctrine | PASS, `deno task arch:check` exit 0 | -| Diff hygiene | PASS, `git diff --check` | -| Review-thread gate | PASS, 0 threads / 0 unanswered | -| Package publish dry-runs | PASS for contracts, SDK, plugin, and auth core | -| JSR package audit | contracts/SDK/auth core exit 0; plugin exit 1 on four pre-existing module-tag plus cardinality findings | -| Structured doc lint | Pre-existing private refs: contracts 9, SDK 3, plugin 15, auth core 4 | +| Gate | Result | +| ------------------------ | -------------------------------------------------------------------------------------------------------- | +| Exact base/merge-base | PASS at `fac9e339042c5394bf882311657d8981d353a1c3` | +| RFC/harness formatting | PASS, eight tracked Markdown files checked | +| Focused RFC links | PASS, 1 document, 0 broken links/anchors | +| Repository docs links | PASS, 102 documents, 0 broken links/anchors | +| Docs accuracy | PASS | +| Exact-shape type proof | PASS; required/optional context, conflicts, 16 accepted, 17 rejected | +| Doctrine | PASS, `deno task arch:check` exit 0 | +| Diff hygiene | PASS, `git diff --check` | +| Review-thread gate | PASS, 0 threads / 0 unanswered | +| Package publish dry-runs | PASS for contracts, SDK, plugin, and auth core | +| JSR package audit | contracts/SDK/auth core exit 0; plugin exit 1 on four pre-existing module-tag plus cardinality findings | +| Structured doc lint | Pre-existing private refs: contracts 9, SDK 3, plugin 15, auth core 4 | +| Audit input | PASS; 59 lines, SHA-256 `fa8b0ab5cd1afd57b8f6c20036a265fa7c8fb48764f88f97f289c44c0737d3d0` | +| Stable dependency audit | Seven oRPC v1.14.x dependencies behind to stable v1.15.0; no dependency mutation | +| Impact scan | 91 `@orpc/*` reference files; 74 after excluding test paths/name patterns | +| Upstream audit | Official releases/migration/request-header/TanStack/error docs and beta.25 codec/retry source reconciled | +| Amendment gates | PASS; eight-file format, RFC/repo links, docs accuracy, type proof, doctrine, diff hygiene | The JSR/doc-lint findings are implementation baselines, not failures introduced by this docs PR and not waivers. No runtime/scaffold E2E was run because this RFC changes no framework or generated @@ -94,12 +128,18 @@ No issue or milestone was mutated. After RFC acceptance, the maintainer/root orc 1. reconcile #1348 acceptance with the narrow header/context/cache law; 2. narrow #1349 to descriptor, composer, context/query propagation, and cache safety; 3. keep #1350 as exact base error-map plus metadata repair; -4. keep #1351 as SDK-owned transport consolidation and coherent oRPC-family update; +4. keep #1351 as SDK-owned transport consolidation and, only after a separate low-risk decision, an + exact-family stable-v1.15.0 update; do not put v2 in RFC-A; 5. place bearer convention, redaction, and auth delivery under #1352; 6. re-scope #1353 from a trace contribution to trace ownership/reserved-header conformance; 7. file the locale proof child only after acceptance; -8. cross-link generic discovery #1093; and -9. keep custom link #451 and later #928/#934/#884 work independent except for shared vocabulary. +8. cross-link generic discovery #1093; +9. keep custom link #451 and later #928/#934/#884 work independent except for shared vocabulary; and +10. propose a separate oRPC v2 migration RFC/spike after RFC-A review, without filing it in this + run. It owns stable/beta policy, atomic exact-family versions, coordinated/parallel endpoints, + route/meta/OpenAPI/Scalar, errors/status, middleware counts, GET/CSRF, OTel topology, desktop + serialization, SSE/streams, query/cache safety, runtime matrix, full CLI/scaffold E2E, docs, and + publish dry-run. ## Exact Fable Reviewer Instructions @@ -108,13 +148,14 @@ new authoring or evaluator session from this branch. Read in this order: -1. `rfcs/0000-sdk-client-contributions.md`; -2. `research.md`, especially the proposal challenge, current API evidence, board state, upstream +1. `.llm/tmp/orpc-v2-audit-followup.md` as the root-requested research amendment input; +2. `rfcs/0000-sdk-client-contributions.md`; +3. `research.md`, especially the proposal challenge, current API evidence, board state, upstream sources, type probe, and JSR consequences; -3. `plan.md`, including the locked decisions, risks, Plan Gate self-audit, and issue map; -4. `worklog.md` `## Design` and exact gate table; -5. `drift.md`; and -6. the carried proposal at +4. `plan.md`, including the locked decisions, risks, Plan Gate self-audit, and issue map; +5. `worklog.md` `## Design` and exact gate table; +6. `drift.md`; and +7. the carried proposal at `/home/codex/repos/netscript-fable5-remediation-plan/.llm/runs/plan-fable5-remediation-roadmap--seed/fable-5-remediation-plan/rfcs/RFC-A-sdk-client-composition.md`. Perform a cross-RFC Plan & Design review, not implementation. Specifically try to falsify: @@ -125,8 +166,13 @@ Perform a cross-RFC Plan & Design review, not implementation. Specifically try t - auth and locale cache isolation across direct, server-query, and TanStack paths; - redaction, cleartext, redirect, abort, and retry guarantees; - transport/final-trace ownership and #451 separation; -- static plugin availability versus explicit activation; and -- compatibility, JSR declaration boundaries, staged issue ownership, and executable gates. +- static plugin availability versus explicit activation; +- compatibility, JSR declaration boundaries, staged issue ownership, and executable gates; +- upstream-major neutrality and the sufficiency of the three internal adapter ports; +- prepare-once correctness under actual stable-v1 retry behavior, including wrapper versus memo; +- procedure metadata and incoming server request-header direct-call behavior; and +- the boundary and complete gate set for the separate v2 migration, especially GET/CSRF, + mixed-version endpoints, and OTel span ownership. For every finding, cite an RFC heading and repository/upstream evidence, classify it as blocking or FCP-safe, and state the smallest correction. Explicitly say whether both auth and locale can be diff --git a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/supervisor.md b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/supervisor.md index beb60953f9..b71e967788 100644 --- a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/supervisor.md +++ b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/supervisor.md @@ -39,6 +39,7 @@ Written at run start per `workflow/lane-policy.md` § Supervisor identity. root-requested post-generator oRPC v2 research amendment. - Pre-amendment RFC/research commit: `89ae608ea935ba8b2776d55e7cb5a09cc29e2520`; pre-amendment handoff HEAD: `e78ac0a65f5475ed37152272b16ba7d89deca8c3`. +- Reviewable amended RFC/research commit: `7a0d398087a6608ff1a55bb9fe4c47158edb72a7`. - The amended RFC is returned to `status:plan-eval` only after focused gates, an explicit-refspec push, and a structured PR phase comment. - The exact Fable entry point and prohibited mutations are in `final-handoff.md`. diff --git a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/worklog.md b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/worklog.md index af0ecc4ff6..ef963cb63f 100644 --- a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/worklog.md +++ b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/worklog.md @@ -165,6 +165,7 @@ considered complete. | 2026-08-08 | 4 | repository scope | Focused scan: 91 `@orpc/*` files, 74 excluding test patterns; stable tool reports all seven workspace oRPC dependencies behind to v1.15.0. | | 2026-08-08 | 4 | design amendment | Locked zero-oRPC public declarations, three internal ports, prepare-once retry law, stable-v1 implementation, and separate v2 RFC/spike gates. | | 2026-08-08 | 4 | focused validation | Re-ran eight-file format, RFC/repository links, docs accuracy, type proof, doctrine, and diff hygiene; all verdict commands exit 0. | +| 2026-08-08 | 4 | amendment commit | Committed the reviewable RFC/research amendment as `7a0d398087a6608ff1a55bb9fe4c47158edb72a7`; handoff-only commit and explicit-refspec push remain. | ## Decisions @@ -220,8 +221,10 @@ considered complete. | Amendment type proof | ignored exact-shape Deno probe | PASS | | Amendment doctrine | `deno task arch:check` | PASS, exit 0; warning-only baseline unchanged | -The root-requested amendment content gates are complete. Its commit, explicit-refspec push, final PR -reconciliation, and external Fable/Qwen verdicts remain pending at this checkpoint. +The root-requested amendment content gates and reviewable commit are complete. The final +explicit-refspec push and live PR reconciliation follow the handoff-only commit, so their exact HEAD +and lifecycle evidence are recorded in the structured PR comment. External Fable/Qwen verdicts +remain pending by owner instruction. ## Handoff Notes From f1a29fe1a65d59f71a59bf4b6b2a48fc49e1e86f Mon Sep 17 00:00:00 2001 From: Rickylabs Date: Sat, 8 Aug 2026 20:18:03 +0200 Subject: [PATCH 06/12] =?UTF-8?q?docs(harness):=20record=20PLAN-EVAL=20ver?= =?UTF-8?q?dict=20for=20RFC-A=20=E2=80=94=20FAIL=5FPLAN=20cycle=201?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cross-family evaluator (Fable 5 high, owner-designated). Ten findings F-A1..F-A10; core thesis verified incl. prepare-once reproduced on locked v1.14.6. Deep-dive delegations recorded (wf_b3416478-edf, Opus 5 xhigh). Co-Authored-By: Claude Fable 5 --- .../plan-eval.md | 159 ++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 .llm/runs/docs-rfc-sdk-client-contribution--rfc/plan-eval.md diff --git a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/plan-eval.md b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/plan-eval.md new file mode 100644 index 0000000000..38143d8f4c --- /dev/null +++ b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/plan-eval.md @@ -0,0 +1,159 @@ +# PLAN-EVAL — docs-rfc-sdk-client-contribution--rfc (RFC-A, PR #1390) + +| Field | Value | +| --- | --- | +| Verdict | **FAIL_PLAN** (PR-comment vocabulary: CHANGES_REQUESTED) — cycle 1 of 2 | +| Evaluator | Claude Fable 5 · high — owner-designated cross-family PLAN-EVAL authority (in-turn owner directive, 2026-08-08), separate session/family from the generator (Codex GPT-5.6 Sol xhigh, thread `019fe242-2bd9-7ff3-8044-bd9d09585397`) | +| Route override | The lane-policy Minimax-over-OpenRouter route is superseded by explicit owner direction: this Fable session evaluates; OpenRouter/OpenHands/Qwen prohibited here; the root orchestrator owns a later Qwen 3.8 Max adversarial pass | +| Evaluated | RFC `rfcs/0000-sdk-client-contributions.md` @ `7a0d39808` (branch HEAD `7be129d80`), run artifacts, PR #1390 body+comments, live board (#1348–#1353, #451, #928, #934, #1093), worktree source at baseline `fac9e339042c` | +| Delegations | Workflow `wf_b3416478-edf` (script committed pre-execution on the seed-run branch): `dd:orpc-v2-audit` + `dd:rfc-a-types`, both Opus 5 · xhigh, read-only/return-only; evidence synthesized and adopted by this evaluator after review | + +## Plan-gate checklist walk + +| Box | Status | Evidence | +| --- | --- | --- | +| Research present and current | ✓ | `research.md` re-baselines the 755-line carried proposal against `fac9e339042c`, live board, locked oRPC 1.14.6, and primary upstream sources; spot-checks below confirmed its load-bearing findings (closed 9-field options, unused `port`/`timeout`, v2 status) | +| Decisions locked | ✓ | 20-row locked-decision table (`plan.md`), each with rationale; proposal-challenge record adjudicates every carried-in choice | +| Open-decision sweep | **✗** | The RFC's 11 FCP questions are individually safe, but the evaluator sweep found **six open decisions the plan did not flag** that force rework if deferred (Findings 1–6). Per the gate: automatic unchecked box | +| Commit slices | ✓ | Docs-run slices S1–S3 executed and evidenced; implementation staged in 8 ordered stages with owners and exit conditions | +| Risk register | ✓ | Present with mitigations; drift-watch list is strong | +| Gate set selected | **✗** | The zero-oRPC-symbol gate is **unpassable as written** (Finding 1); the private-port claim has no asserting gate (Finding 6) | +| Deferred scope explicit | ✓ | Non-goals + separate v2 RFC boundary are exemplary | +| jsr-audit | ✓ | Four-package baseline audit + publish-consequence table present; baselines recorded, not waived | + +## Verdict: FAIL_PLAN — findings (severity-ranked) + +**None of the following overturns the RFC's core thesis.** Headers + typed per-call context, the +three private ports, prepare-once above retry, partition/direct-only cache law, auth+locale +dogfoods, upstream-major neutrality, and stay-on-stable-v1 are all **verified sound** — including +by execution against the locked family. The failures are completeness failures at the gate bar. + +### F-A1 (critical) — The zero-oRPC-symbol gate fails on unchanged code; scope it + +RFC "Conformance and fitness gates" (type gates, last bullet) and the publish gate apply a +zero-oRPC-symbol scan to public/generated declarations including `contracts`. Executed evidence: +`deno doc --json packages/sdk/src/ports/mod.ts` contains `~orpc` ×2 — `ContractProcedureLike` +(`ports/service-client.ts:78-86`) requires the literal `'~orpc'` metadata-accessor property, and +`ContractLike` is the bound on `CreateServiceClientOptions` — the exact type RFC-A +extends. Doctrine `02-public-surface.md:218-240` further *sanctions* raw `@orpc/contract` builder +types in `packages/contracts` (`BaseContract = ReturnType`, +`BaseContractRoute = ContractProcedureBuilderWithInputOutput<…>`). +**Repair:** scope the gate normatively — it binds (a) the new RFC-A protocol/descriptor/context +types and (b) generated client declarations; pre-existing `ContractLike`/contracts leakage is +named existing debt owned by #1350/#1278, with the gate's allowlist referencing those issues. +Without this the first implementation PR either fails its own gate or silently waives it. + +### F-A2 (critical) — Server query-key algebra: the partition suffix changes public exported types the RFC never names + +The RFC specifies the suffix only for TanStack full keys. The server path has a **fixed public +3-tuple**: `createActionQueryKey(): readonly [string, string, string]` +(`ports/query-key.ts:36-42`), `ActionMethod.key: (props) => readonly [string, TAction, string]` +(`ports/query-factory.ts:57-59`), plus `CacheKey = Deno.KvKey` (`ports/cache-store.ts:24`), +`key-bridge.ts`, `kv-cache-persister.ts`, and `collections/create-query-collection.ts` — none +mentioned. Also: TanStack key injection is not free — `optionsIn.queryKey` must be precomputed +per procedure × option-kind × nesting level, replacing today's zero-cost cast +(`create-service-query-utils.ts:57-63`), and the checked-in fixture +`tests/type-fixtures/service-query-utils-upstream_type.ts:39-40` pins upstream assignability that +a context-generic `ServiceQueryUtils` breaks. +**Repair:** add a normative "server key algebra" subsection deciding the suffix's type-level shape +on the 3-tuple surfaces (or explicitly widening them with compatibility defaults), enumerate the +six touched surfaces, acknowledge the wrap cost, and disposition the upstream-assignability +fixture. Deferring this reworks Stage 2. + +### F-A3 (major) — The additive-compatibility claim is contradicted by the type sketches + +`ServiceClientMethod` and `ServiceClientShape` +are shown without context defaults yet are public exports (`client/mod.ts:16-33`, +`ports/mod.ts:65-83`); `ServiceQueryClientContext = Record` is public too. As +written this is a breaking public type change, contradicting "additive for consumers that do not +opt in". **Repair:** state compatibility defaults (`TContext extends object = +ServiceClientContext` / `Record` as appropriate) on every widened public generic. + +### F-A4 (major, security) — Streaming reconnect under prepare-once: frozen credential + +Verified on the locked family: the v1 retry plugin re-enters `next({error})` from inside +async-iterator consumption (`@orpc/client@1.14.6` `plugins/index.mjs:337-360`) — after the +logical call has returned. Under prepare-once, a long-lived SSE/stream procedure reconnects +indefinitely with the original prepared credential. The mandatory fixture only forces "at least +one retry". **Repair:** an explicit rule — e.g. streaming procedures with a credential-bearing +contribution are reconnect-bounded, reconnect constitutes a new logical call (re-prepare), or +streaming is `direct-only`/no-retry in v1 — plus a fixture covering iterator-phase reconnect. +This lands directly on the auth dogfood. + +### F-A5 (major) — Desktop transport bypass unaddressed + +`@netscript/sdk/desktop` (`desktop-rpc-client.ts:1-32`) constructs a second `createORPCClient` +over a MessagePort link; contributions attached via `createServiceClient` never apply. A desktop +webview calling the same contract silently sends no bearer. **Repair:** scope the desktop link +in, out, or explicitly rejected-with-consequence; if out, the auth-core docs must state the +boundary. + +### F-A6 (major) — Private-port location and absence gate + +`src/ports/` is the **public** `@netscript/sdk/ports` barrel; the RFC never states where the +three private ports live, and no conformance gate asserts their absence from `deno doc` despite +the normative MUST-NOT-appear claim. **Repair:** name the private location (e.g. `src/internal/`) +and add the absence assertion to the adapter-compatibility gates. + +### F-A7 (medium) — `ServiceClientContext` retry fields are upstream-shaped and contribution-visible + +`retry|retryDelay|shouldRetry|onRetry` are a hand-copy of `ClientRetryPluginContext` +(intersected at `http-client-link.ts:27`); their semantics are the upstream plugin's, and +`SdkClientPrepareOptions.context` exposes them to every contribution — making the public protocol +upstream-*coupled* while upstream-type-*free*. Related mechanics the RFC must state: retry is off +by default (`{default:{retry:0}}`), so the forced-retry fixture must drive `context.retry`; and +the dedupe plugin replaces downstream context (`plugins/index.mjs:236-248`) so the +"same immutable snapshot on every attempt" gate wording collides with an existing context-swap +path (signal/cache read from the replaced context). **Repair:** either define NetScript-owned +semantics for the retry fields or exclude them from the contribution-visible context projection; +reword the snapshot gate to the contributor-header/context projection it actually governs; state +the prepared-header channel (private context symbol vs wrapper) explicitly. + +### F-A8 (medium) — v2-audit amendment corrections (adopt into the RFC + v2 gate list) + +The amendment's status facts are **verified accurate** (v1.15.0 stable, `2.0.0-beta.26` +pre-release, `middleapi/orpc` is the correct repo — the charter's `dinwwwh` is stale), and +`RequestHeadersHandlerPlugin` is correctly treated as an incoming-server companion (confirmed in +shipped v2 types: `reqHeaders?: Headers | undefined`, handler plugin, not a client seam). Four +corrections: (a) **GET direction is inverted** — GET inference is enabled *today* +(`http-client-link.ts:82`); v2 *rejects* GET by default (`allowMethods` defaults to +POST/PUT/PATCH/DELETE, verified in shipped beta.26 source). Rewrite the boundary and Q10 as +keep-GET (server `allowMethods` + Sec-Fetch-Mode CSRF story) vs accept-losing-GET. (b) v2 removes +`inferRPCMethodFromContractRouter` (absent from all three beta.26 packages) — the exact symbol at +`http-client-link.ts:17`; add re-implementation to the v2 gate list. (c) The GET-only dedupe +filter (`http-client-link.ts:109`) becomes a silent no-op if v2 lands without GET — add a +dedupe-effectiveness gate. (d) `@orpc/opentelemetry` already ships on the v1 line (1.14.11+, not +deprecated) — the package-rename decision belongs to #1351, only span-topology/double-span proof +is v2-scoped. Also state that only `deno.lock` pins the family (all manifests are `^1.14.6`) — +name lock-only pinning as the gate for the "separate v1.15.0 decision" or require exact pins. + +### F-A9 (minor) — Inference-budget evidence is not reproducible in-tree + +The probe is gitignored and excluded from the repo checker, and it models a stripped +`ServiceClientContext`, not the real `ContractLike`/`defineServices`/`ServiceQueryUtils` algebra. +**Repair:** commit the type fixture in-tree (tests/type-fixtures) modeling the real surfaces +before the 16-budget is ratified; keep the numbers informational. + +### F-A10 (minor, adopt-as-strengthening) + +Prepare-once per-attempt behavior is now **verified on locked v1.14.6** (headers resolve in +`encode`, retry re-enters upstream of it) — upgrade the RFC's "must be tested rather than +assumed" to cited fact. Dedupe is header-safe (key includes headers) — state it. Stage-0 +reconciliation of #1350's live scope (its filed title is the `safe()` repair; RFC Stage 1 adds +metadata initialization) is already planned — keep it explicit. `input: unknown` reaching +third-party `prepare` deserves one privacy sentence. v1.15.0 shipped hours *after* beta.26 — +v1 is actively maintained; this strengthens the stay-on-v1 decision. + +## FCP-question adjudication + +Q1–Q4, Q7–Q9, Q11: safe to defer (policy/naming/sequencing; no rework risk). Q5 (wrapper vs +memo): safe **only after** F-A7's context-channel statement lands — both realizations then remain +fixture-provable. Q6 (metadata placement): safe; the vocabulary itself is normative either way. +Q10: must be **rewritten** per F-A8(a) before FCP — as posed it gates the wrong direction. + +## Required for PASS (cycle 2) + +Amend the RFC to resolve F-A1–F-A6 and F-A8(a); fold F-A7's statements and F-A8(b–d) into the +gate lists; F-A9/F-A10 may land as part of the same edit or as recorded stage conditions. No +structural redesign is requested; every repair is a scoped amendment to an RFC whose core law +survived adversarial verification. From 78a7cecd1d5eaafa7a65bc25a21af497567128dc Mon Sep 17 00:00:00 2001 From: Rickylabs Date: Sat, 8 Aug 2026 20:52:52 +0200 Subject: [PATCH 07/12] docs(rfc): resolve sdk contribution plan findings --- .../context-pack.md | 125 +++-- .../drift.md | 31 ++ .../final-handoff.md | 284 ++++------ .../plan.md | 142 +++-- .../research.md | 72 ++- .../supervisor.md | 20 +- .../worklog.md | 175 +++--- .../sdk-client-contributions-rfc_type.ts | 503 +++++++++++++++++ rfcs/0000-sdk-client-contributions.md | 510 ++++++++++++++---- 9 files changed, 1385 insertions(+), 477 deletions(-) create mode 100644 packages/sdk/tests/type-fixtures/sdk-client-contributions-rfc_type.ts diff --git a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/context-pack.md b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/context-pack.md index 118486d80c..ffa5084093 100644 --- a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/context-pack.md +++ b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/context-pack.md @@ -2,23 +2,25 @@ ## Run Metadata -| Field | Value | -| -------------- | ------------------------------------------------------ | -| Run ID | `docs-rfc-sdk-client-contribution--rfc` | -| Branch | `docs/rfc-sdk-client-contribution` | -| Current phase | `plan-eval`; awaiting owner-directed Fable/Qwen review | -| Archetype | `2 + 4 + 5 + 6` described; docs-only PR | -| Scope overlays | `SCOPE-docs` | -| PR | `https://github.com/rickylabs/netscript/pull/1390` | +| Field | Value | +| -------------- | ----------------------------------------------------------------------- | +| Run ID | `docs-rfc-sdk-client-contribution--rfc` | +| Branch | `docs/rfc-sdk-client-contribution` | +| Current phase | `plan-eval`; cycle-1 remediation ready for owner-directed Fable cycle 2 | +| Archetype | `2 + 4 + 5 + 6` described; docs-only PR | +| Scope overlays | `SCOPE-docs` | +| PR | `https://github.com/rickylabs/netscript/pull/1390` | ## Current State The RFC is authored at `rfcs/0000-sdk-client-contributions.md` and keeps `0000`/Draft. It rejects the starting single “everything” envelope and ratifies a narrow, versioned request-header preparation axis. Research, type proof, current JSR/doc-lint baselines, live board state, and -primary upstream sources are recorded. A root-requested post-generator audit amendment now makes the -seam explicitly upstream-major-neutral, fixes the retry lifecycle, and separates the oRPC v2 -migration. This amendment is not an evaluator verdict. No product source is changed. +primary upstream sources are recorded. A root-requested post-generator audit amendment made the seam +explicitly upstream-major-neutral and separated the oRPC v2 migration. Formal Fable PLAN-EVAL cycle +1 then returned authoritative `FAIL_PLAN / CHANGES_REQUESTED`; this authoring pass resolves F-A1 +through F-A10 without claiming PASS. No framework implementation is included; the only TypeScript +addition is a compile-only RFC type fixture. ## Decision Snapshot @@ -36,12 +38,24 @@ migration. This amendment is not an evaluator verdict. No product source is chan defaults to `none`. - SDK transport retains discovery/codec/fetch/retry/dedupe/trace/errors. Trace fields are reserved; #1353 is a trace-ownership proof, not a contribution. -- Public/generated declarations contain zero raw oRPC symbols. Three internal NetScript ports - isolate procedure metadata, prepared outbound headers, and transport policy. -- Preparation runs once per logical call above retry; each attempt sees byte-equivalent immutable - contributor headers/context. Outer wrapper versus memo is an internal Fable question. -- RFC-A implements against stable v1 (optionally v1.15.0 after a separate exact-family decision). v2 - beta/protocol/errors/GET/OTel/serialization/streaming migration is a separate RFC/spike. +- Named new RFC-A declaration nodes and all generated client declarations contain zero raw oRPC + symbols; existing `ContractLike`/contracts leakage is a non-growing #1350/#1278 baseline. Three + internal NetScript ports live only at `packages/sdk/src/internal/client-contributions/`, with + negative doc and packed-import gates. +- Contributors see only their declared-context projection plus signal; SDK retry/cache/trace/dedupe + semantics and the private prepared-call channel remain transport-owned. +- Preparation runs once per unary logical-call epoch above retry; each ordinary retry sees + byte-equivalent immutable contributor headers/context. Iterator-phase reconnect starts a fresh + epoch and refreshes credentials. Outer wrapper versus memo remains an internal realization choice. +- Every widened public generic has an old-shape default. Default server keys remain exact + three-tuples; partitioning adds one canonical two-element suffix for exact five-tuples through + factories, cache bridge/persister/collections, and recursive TanStack wrappers. +- RFC-A is HTTP-only. Desktop MessagePort clients reject contribution selection in types, + construction, and generation rather than silently omitting auth. +- RFC-A implements against stable v1 (optionally v1.15.0 after a separate lock-only whole-family + decision). The v2 spike must choose preserve-current-GET with replacement inference plus + `allowMethods`/CSRF or retire GET and replace dedupe; protocol/errors/OTel/serialization/streaming + migration remains separate. - The server request-header handler is only an optional incoming companion and may be absent for direct calls. - Plugin discovery registers static module/export/targets; generated/app config explicitly selects @@ -50,11 +64,11 @@ migration. This amendment is not an evaluator verdict. No product source is chan ## Files Changed -| Path | Status | Notes | -| -------------------------------------------------- | --------------- | ----------------------------------------------------- | -| `rfcs/0000-sdk-client-contributions.md` | new | Decision-complete RFC; no product implementation. | -| `.llm/runs/docs-rfc-sdk-client-contribution--rfc/` | updated/new | Mandatory harness evidence plus launch records. | -| `.llm/tmp/sdk-client-contribution-probe.ts` | ignored scratch | Non-product inference/conflict proof; not part of PR. | +| Path | Status | Notes | +| ----------------------------------------------------------------------- | ----------- | ----------------------------------------------------------------- | +| `rfcs/0000-sdk-client-contributions.md` | new | Cycle-1-remediated architecture RFC; no framework implementation. | +| `packages/sdk/tests/type-fixtures/sdk-client-contributions-rfc_type.ts` | new | Compile-only real-surface inference/default/key proof. | +| `.llm/runs/docs-rfc-sdk-client-contribution--rfc/` | updated/new | Mandatory harness evidence, formal verdict, and handoff records. | ## Live Board Snapshot @@ -68,29 +82,34 @@ migration. This amendment is not an evaluator verdict. No product source is chan ## Gate Snapshot -| Gate | Status | Evidence | -| ------------------------------- | ---------------- | ------------------------------------------------------------------------------- | -| RFC formatting | pass | `deno fmt --check` | -| RFC internal links | pass | focused repo link checker, 0 broken | -| Repository docs links/accuracy | pass | both tasks exit 0 | -| Type probe | pass | Deno check; 16 accepted/17 rejected fixture | -| Package dry-run baseline | pass | contracts/sdk/plugin/auth-core all report dry-run OK | -| JSR package audit | baseline finding | plugin audit exit 1 on pre-existing module tags/cardinality; other three exit 0 | -| Doc-lint baseline | baseline finding | combined private refs 9/3/15/4 respectively; RFC adds none | -| Doctrine | pass | `deno task arch:check` exits 0; existing warnings are baseline | -| Plan Gate self-audit | pass | complete for external evaluator entry; no evaluator verdict claimed | -| Audit amendment evidence | pass | 59-line input hashed; 91/74 file scan; seven v1 dependencies behind to 1.15.0 | -| Audit amendment gates | pass | format, links, accuracy, type proof, doctrine, and diff hygiene | -| Pre-amendment PR reconciliation | pass | draft, required labels, sole `status:plan-eval`, no milestone/closing keyword | -| Amendment PR reconciliation | external record | final pushed HEAD and sole `status:plan-eval` are recorded in the phase comment | +| Gate | Status | Evidence | +| ------------------------------- | ------------------ | ------------------------------------------------------------------------------- | +| RFC formatting | pass | `deno fmt --check` | +| RFC internal links | pass | focused repo link checker, 0 broken | +| Repository docs links/accuracy | pass | both tasks exit 0 | +| Type fixture | pass | In-tree Deno check; real defaults/key shapes plus 16 accepted/17 rejected | +| Package dry-run baseline | pass | contracts/sdk/plugin/auth-core all report dry-run OK | +| JSR package audit | baseline finding | plugin audit exit 1 on pre-existing module tags/cardinality; other three exit 0 | +| Doc-lint baseline | baseline finding | combined private refs 9/3/15/4 respectively; RFC adds none | +| Doctrine | pass | `deno task arch:check` exits 0; existing warnings are baseline | +| PLAN-EVAL cycle 1 | fail/remediated | Fable F-A1–F-A10 accepted; cycle-2 PASS remains external | +| Audit amendment evidence | pass | 59-line input hashed; 91/74 file scan; seven v1 dependencies behind to 1.15.0 | +| Audit amendment gates | pass | format, links, accuracy, type proof, doctrine, and diff hygiene | +| Pre-amendment PR reconciliation | pass | draft, required labels, sole `status:plan-eval`, no milestone/closing keyword | +| Cycle-1 remediation gates | pass | format/lint/type, RFC/repo links, accuracy, doctrine, and diff hygiene exit 0 | +| Cycle-2 PR reconciliation | pending final step | final pushed HEAD and sole `status:plan-eval` will be recorded in phase comment | ## JSR Consequences - No new contracts/SDK/plugin subpaths; root/client/ports/config symbols expand. - Auth core adds `./sdk` and possibly a constrained `./sdk/server` export. -- No oRPC public type may leak into declarations. -- The stronger implementation gate is zero raw oRPC module specifiers or symbols in all public and - generated declarations. +- No oRPC identity may leak into the named new RFC-A protocol nodes or generated client + declarations. +- The implementation gate uses symbol-filtered `deno doc --json` on the new nodes plus a full + generated-declaration scan; unchanged `ContractLike`/contracts leakage is allowlisted only under + #1350/#1278 and cannot grow. +- Private adapter identifiers must be absent from SDK root/client/ports/desktop docs and fail packed + consumer imports from both root and guessed subpaths. - Implementation must reduce or isolate existing private-type references, preserve precise error and metadata types, and pass doc-lint/publish/consumer gates. @@ -98,25 +117,32 @@ migration. This amendment is not an evaluator verdict. No product source is chan 1. Amend #1348 acceptance to the narrow header/context/cache law after RFC acceptance. 2. Narrow #1349 to descriptor/composer/context/query-safety work. -3. Keep #1350 exact error/metadata repair and #1351 SDK-owned transport consolidation. +3. Keep #1350's filed `safe()` error repair as Stage 1a; Stage 0 must either explicitly expand it or + select a dependent Stage 1b owner for procedure metadata. Keep #1351 SDK-owned transport + consolidation. 4. Place bearer convention in auth core under #1352. 5. Re-scope #1353 to final trace injection/reserved-key conformance. 6. File a locale proof child only after acceptance. 7. Cross-link #1093 and keep #451 independent. 8. Propose, but do not file in this run, a separate oRPC v2 migration RFC/spike with stable/beta, atomic family, rollout/endpoints, route/meta/OpenAPI/Scalar, error/status, middleware-count, - GET/CSRF, OTel, desktop serializer, streams, cache, runtime matrix, E2E, docs, and publish gates. + replacement method inference, `allowMethods`/GET/CSRF, dedupe effectiveness, OTel topology, + Desktop MessagePort serialization, SSE/reconnect credentials, cache, runtime matrix, + package/CLI/scaffold E2E, docs snippets, and publish gates. ## External Reviewer Entry Point Read, in order: -1. `rfcs/0000-sdk-client-contributions.md`; -2. `research.md` proposal challenge and API/board evidence; -3. `plan.md` locked decisions, gates, and issue reconciliation; -4. `worklog.md` Design and gate results; -5. `drift.md` for owner-authorized evaluator routing and design drift; and -6. `.llm/tmp/orpc-v2-audit-followup.md` as the root-requested post-generator research input. +1. `plan-eval.md` in full as the authoritative cycle-1 finding set; +2. `rfcs/0000-sdk-client-contributions.md`, checking F-A1 through F-A10 against its normative laws + and gates; +3. `packages/sdk/tests/type-fixtures/sdk-client-contributions-rfc_type.ts`; +4. `research.md` formal-amendment table and API/board evidence; +5. `plan.md` locked decisions, gates, and issue reconciliation; +6. `worklog.md` Design and gate results; +7. `drift.md` for formal evaluator drift and owner-authorized routing; and +8. `.llm/tmp/orpc-v2-audit-followup.md` as the earlier root-requested research input. The reviewer must not implement product code, assign an RFC number, merge, close issues, or mutate milestones. Findings should cite RFC headings and classify blocking versus safe FCP feedback. @@ -127,5 +153,6 @@ milestones. Findings should cite RFC headings and classify blocking versus safe - RFC/research: `89ae608ea935ba8b2776d55e7cb5a09cc29e2520`. - Handoff baseline: `e78ac0a65f5475ed37152272b16ba7d89deca8c3`. - Audit amendment: `7a0d398087a6608ff1a55bb9fe4c47158edb72a7`. -- The handoff-only commit and per-slice PR comment complete the V3 commit record; the PR comment +- Formal evaluator artifact: `f1a29fe1a65d59f71a59bf4b6b2a48fc49e1e86f`. +- Cycle-1 remediation and final handoff commits are recorded here after creation; the PR comment records the final pushed HEAD because an artifact cannot contain its own commit id. diff --git a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/drift.md b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/drift.md index 9149048c07..9caa8dcf13 100644 --- a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/drift.md +++ b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/drift.md @@ -97,3 +97,34 @@ documentation. - **Evidence:** amended RFC sections “Procedure metadata,” “Internal adapter ports,” “Async context, retries, and cancellation,” “Transport ownership and oRPC alignment,” “Compatibility and migration,” and “Staged implementation plan and issue decomposition.” + +## 2026-08-08 — Formal PLAN-EVAL cycle 1 found ten completeness defects + +- **What:** Claude Fable 5 returned authoritative `FAIL_PLAN / CHANGES_REQUESTED` for cycle 1. The + core contribution axis survived, but its gates and compatibility record omitted six + implementation-forcing decisions and four evidence/board corrections (F-A1 through F-A10). +- **Source:** `plan-eval.md`, 159 lines as received at evaluator commit + `f1a29fe1a65d59f71a59bf4b6b2a48fc49e1e86f`; SHA-256 + `0690af2a2914ad0a9118be04ccebb933af33b2bac8f3f743bc7990f8f5f38cdd`. +- **Expected:** The post-audit RFC would be decision-complete for implementation and have executable + gates. +- **Actual:** A whole-graph zero-oRPC scan could not pass unchanged `ContractLike`; server key + algebra and generic defaults were incomplete; retry preparation could freeze stream credentials; + Desktop bypass and private port placement were unstated; transport retry fields leaked into the + contribution view; the v2 GET direction/gates were incomplete; the inference proof was ignored; + and #1350 metadata ownership needed an explicit stage split. +- **Severity:** authoritative formal evaluator failure, cycle 1 of 2. This supersedes any earlier + generator readiness self-audit; it does not overturn the extension-axis design. +- **Action:** scope zero-upstream inspection to named new RFC-A/generated declaration nodes under a + non-growing #1350/#1278 baseline; specify exact default 3-tuple/partitioned 5-tuple algebra across + six server/cache surfaces and recursive TanStack wrapping; default every widened generic; make + iterator reconnect a fresh preparation epoch; reject HTTP contributions on Desktop; locate and + negatively test the private ports; expose only contribution-declared context plus signal; correct + the v2 preserve-GET/retire-GET fork and complete its gates; commit a real-surface 16/17 fixture; + and split #1350 Stage 1a from metadata Stage 1b ownership. +- **Evidence:** revised RFC sections “Internal adapter ports,” “Tuple type algebra,” “Query and + generated type propagation,” “Server key algebra and compatibility,” “Async context, retries, and + cancellation,” “Desktop transport boundary,” “Boundaries reserved for the v2 migration,” + “Compatibility and migration,” and “Conformance and fitness gates”; committed fixture + `packages/sdk/tests/type-fixtures/sdk-client-contributions-rfc_type.ts`; remediation tables in + `research.md` and `worklog.md`. diff --git a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/final-handoff.md b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/final-handoff.md index 02a554790e..b6b909b562 100644 --- a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/final-handoff.md +++ b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/final-handoff.md @@ -1,185 +1,115 @@ -# Final Handoff: typed SDK client contributions RFC +# Final Handoff: RFC-A PLAN-EVAL cycle-1 remediation ## Delivery Identity -| Field | Value | -| ------------------- | ----------------------------------------------------------- | -| Draft PR | `https://github.com/rickylabs/netscript/pull/1390` (#1390) | -| Branch | `docs/rfc-sdk-client-contribution` | -| Base | `origin/main` at `fac9e339042c5394bf882311657d8981d353a1c3` | -| Reviewable RFC HEAD | `7a0d398087a6608ff1a55bb9fe4c47158edb72a7` | -| RFC | `rfcs/0000-sdk-client-contributions.md` (`0000`, Draft) | -| Run dir | `.llm/runs/docs-rfc-sdk-client-contribution--rfc/` | -| PR phase | `status:plan-eval` | - -`7a0d398087a6608ff1a55bb9fe4c47158edb72a7` is the exact substantive amended RFC/research commit -reviewed by the generator gates. The commit containing this handoff changes run metadata only; its -pushed SHA is recorded in the amendment PR comment so the handoff does not pretend it can contain -its own Git object id. - -## Outcome - -The carried-in Fable proposal was challenged rather than copied. The RFC ratifies a narrow, -package-owned request-header preparation axis behind three NetScript internal ports. The root's -post-generator oRPC v2 audit was reconciled as research, not an evaluator verdict. RFC-A is now -normatively upstream-major-neutral, implements against stable v1, and leaves the coordinated v2 -migration to a separate RFC/spike. It does not authorize a generic client middleware, raw-link, -transport, query-policy, error-map, or server-plugin framework. - -## Decisions Made - -1. A contribution has protocol `{ family: "netscript.sdk-client", major: 1 }`, a validated id, - runtime required/optional context declaration, exclusive lower-case header keys, a mandatory - response-cache effect, and async `prepare`. -2. A literal tuple infers one context intersection per service. Duplicate id, context, header, - reserved ownership, invalid limits, and widened/JavaScript boundary errors fail explicitly. -3. Contributors run sequentially against the same immutable snapshot and cannot see accumulated - output. Valid disjoint results commute; tuple order selects only the first reported failure. -4. Query use is safe by construction: `invariant`, synchronous non-secret `partitioned`, or - `direct-only`. Partition pairs are id-sorted full-key suffixes; direct-only services are absent - from query/query-utils maps. -5. `@netscript/plugin-auth-core/sdk` owns the bearer factory. Procedure metadata is - `NetScriptProcedureMeta.access.authentication = "none" | "optional" | "required"`, with - first-party unmarked behavior defaulting to `"none"`. -6. Locale/`accept-language` is the non-auth proof. Trace was rejected as dogfood because final W3C - trace fields belong to the client-span transport edge. -7. Discovery adds static module/export/target availability through `@netscript/plugin/config`; - generated/application config explicitly activates literal tuples per service. -8. Discovery, codecs, fetch, retry, dedupe, cancellation, redirects, tracing, and server-defined - errors remain SDK transport policy. Custom links remain exclusively #451. -9. Contribution failures are local stable errors with a fixed diagnostic allowlist. Header values, - input, context, partition source values, resolver messages, and resolver causes do not cross the - error/log/telemetry boundary. -10. Omitted contributions preserve current context, headers, query keys, and mapped result keys. - Existing generic call sites retain defaults; current no-op `port`/`timeout` fields are - deprecated but not removed by this RFC. -11. Public and generated declarations contain zero raw oRPC types, links, plugins, contexts, - interceptors, metadata accessors, or upstream-major aliases. Package-private ports own procedure - metadata, prepared outbound headers, and transport policy. -12. Contribution preparation runs exactly once per logical call above retries. Every attempt - receives byte-equivalent immutable contributor headers/context; direct unmemoized link-header - preparation is non-conforming. -13. `RequestHeadersHandlerPlugin` is only an optional incoming server companion and may have no - headers on direct calls. It does not implement outbound composition, ownership, redaction, or - cache partitioning. -14. RFC-A does not migrate to oRPC v2 beta or adopt v2 error/status, GET/CSRF, or OTel semantics. A - separate v1.15.0 exact-family upgrade may be considered; the broad v2 migration requires its own - RFC/spike and coordinated rollout. - -## FCP-Safe Unresolved Questions - -These implementation/sequencing questions remain open without changing the locked extension law: - -1. Raise the 16-contribution ceiling if CI type evidence supports it; do not ship below 16. -2. Ship an explicit server-only environment credential helper in the first auth slice or keep it as - an application example. -3. Schedule independent custom-link issue #451 alongside implementation or later. -4. Refine public names during FCP without changing defaults, ownership, cache safety, or composition - semantics. -5. Use the preferred outer logical-call wrapper or immutable per-call memoization for prepare-once; - either must pass count `1` and byte-equivalent retry fixtures. -6. Ratify procedure-auth metadata inside RFC-A/#1350 or in a dependent mini-RFC; it must exist - before auth dogfood ships. -7. Install the stable-v1 incoming request-header handler by default in service presets or require - explicit selection; direct calls must tolerate absence under an explicit policy. -8. Upgrade the exact oRPC family to stable v1.15.0 before RFC-A implementation or implement first on - the current v1.14.x baseline. -9. In the separate v2 migration, require zero-downtime parallel endpoints or permit a coordinated - atomic client/server rollout. -10. Confirm that GET enablement and its CSRF law remain transport/v2-migration scope. -11. Determine whether v2 OTel can replace final injection without violating NetScript span ownership - or producing double spans. - -Duplicate rejection, order independence, exactly-once per-logical-call preparation, reserved trace -ownership, zero raw oRPC symbols in public/generated declarations, no upstream callback arrays, -explicit activation, cache safety, separation from contract-defined errors, and no production v2 -beta migration in RFC-A are not open. +| Field | Value | +| ----------------------------- | --------------------------------------------------------------------------------------------- | +| Draft PR | `https://github.com/rickylabs/netscript/pull/1390` (#1390) | +| Branch | `docs/rfc-sdk-client-contribution` | +| Base | `origin/main` at `fac9e339042c5394bf882311657d8981d353a1c3` | +| Formal cycle-1 verdict | `FAIL_PLAN / CHANGES_REQUESTED`; `plan-eval.md` at `f1a29fe1a65d59f71a59bf4b6b2a48fc49e1e86f` | +| Reviewable remediation commit | `REMEDIATION_COMMIT_PENDING` | +| RFC | `rfcs/0000-sdk-client-contributions.md` (`0000`, Draft) | +| Run dir | `.llm/runs/docs-rfc-sdk-client-contribution--rfc/` | +| Requested lifecycle | exactly one `status:plan-eval` after push | + +The PR stays draft. This is author remediation of authoritative Fable findings F-A1 through F-A10, +not a self-evaluation or PASS claim. No RFC number, issue, milestone, merge, evaluator, or product +framework implementation was created or mutated. + +## Cycle-1 Finding Reconciliation + +| Finding | Normative correction | +| ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| F-A1 | The zero-oRPC gate applies to named new RFC-A protocol nodes and all generated client declarations. Existing `ContractLike`/contracts leakage is a non-growing #1350/#1278 allowlist, not an impossible whole-graph prerequisite. | +| F-A2 | Default server keys remain exact three-tuples; partitioning appends `['$netscript.sdk-context', serializedPairs]` for exact five-tuples. The RFC dispositions action/query factories, `CacheKey`/`CacheQuery`, key bridge, KV persister, collections, recursive TanStack wrapping, and the current upstream fixture. | +| F-A3 | Every widened public generic has an explicit compatibility default preserving the current no-contribution shape. | +| F-A4 | Unary/ordinary retries prepare once per logical-call epoch. Iterator-phase stream reconnect is a new epoch and refreshes credentials exactly once; its retries replay that epoch's immutable record. | +| F-A5 | RFC-A v1 is HTTP-only. Desktop MessagePort options do not accept contributions; types, construction, and generators reject attempted selection rather than silently dropping auth. | +| F-A6 | Private ports live only in `packages/sdk/src/internal/client-contributions/`, with no barrel/export. SDK doc-graph and packed-consumer negative tests prove their absence. | +| F-A7 | Contributors see only their declared-context projection plus signal. Retry/cache/trace/dedupe fields and the private prepared-call channel stay transport-owned; forced unary retry uses `context.retry: 1`, and comparison covers only the contribution projection. | +| F-A8 | Stable v1 already infers GET. The v2 spike must preserve GET by replacing removed inference and configuring `allowMethods`/CSRF, or retire GET and replace dedupe. Atomic lock family, dedupe-effectiveness, OTel topology, Desktop, stream, and all other migration gates are explicit. | +| F-A9 | `packages/sdk/tests/type-fixtures/sdk-client-contributions-rfc_type.ts` is committed and imports real contract/client/query/key surfaces while modeling only proposed RFC declarations. | +| F-A10 | Stable-v1 header/retry and header-safe dedupe facts are cited; raw input is sensitive borrowed data; stable v1 remains maintained; Stage 1a keeps #1350's filed `safe()` repair while Stage 0 assigns metadata Stage 1b. | + +The core design is unchanged: a package-owned typed per-call request-header contribution seam, auth +plus locale dogfoods, three private adapter responsibilities, explicit cache effects, stable-v1 +implementation, and upstream-major-neutral public/generated RFC-A declarations. + +## FCP-Safe Questions + +1. Outer wrapper versus immutable per-unary-call memoization; both use the private channel, while + stream reconnect always creates a fresh preparation epoch. +2. Ratify procedure-auth metadata inside RFC-A/#1350 or assign a dependent Stage 1b owner. +3. Install the incoming stable-v1 request-header server companion by default or explicitly; direct + calls must tolerate absent headers. +4. Move the lock-pinned whole oRPC v1 family to v1.15.0 before or after the seam. +5. In the separate v2 RFC, require parallel endpoints or permit an atomic coordinated rollout. +6. In that v2 RFC, preserve current GET with replacement inference/`allowMethods`/CSRF or retire GET + and replace dedupe. +7. Prove whether v2 OTel can replace final injection without violating NetScript span ownership or + creating double spans. v1 package selection/renaming remains #1351. +8. Retain 16 contributions as the minimum supported inference budget; raise it only with CI + evidence. ## Validation Evidence -| Gate | Result | -| ------------------------ | -------------------------------------------------------------------------------------------------------- | -| Exact base/merge-base | PASS at `fac9e339042c5394bf882311657d8981d353a1c3` | -| RFC/harness formatting | PASS, eight tracked Markdown files checked | -| Focused RFC links | PASS, 1 document, 0 broken links/anchors | -| Repository docs links | PASS, 102 documents, 0 broken links/anchors | -| Docs accuracy | PASS | -| Exact-shape type proof | PASS; required/optional context, conflicts, 16 accepted, 17 rejected | -| Doctrine | PASS, `deno task arch:check` exit 0 | -| Diff hygiene | PASS, `git diff --check` | -| Review-thread gate | PASS, 0 threads / 0 unanswered | -| Package publish dry-runs | PASS for contracts, SDK, plugin, and auth core | -| JSR package audit | contracts/SDK/auth core exit 0; plugin exit 1 on four pre-existing module-tag plus cardinality findings | -| Structured doc lint | Pre-existing private refs: contracts 9, SDK 3, plugin 15, auth core 4 | -| Audit input | PASS; 59 lines, SHA-256 `fa8b0ab5cd1afd57b8f6c20036a265fa7c8fb48764f88f97f289c44c0737d3d0` | -| Stable dependency audit | Seven oRPC v1.14.x dependencies behind to stable v1.15.0; no dependency mutation | -| Impact scan | 91 `@orpc/*` reference files; 74 after excluding test paths/name patterns | -| Upstream audit | Official releases/migration/request-header/TanStack/error docs and beta.25 codec/retry source reconciled | -| Amendment gates | PASS; eight-file format, RFC/repo links, docs accuracy, type proof, doctrine, diff hygiene | - -The JSR/doc-lint findings are implementation baselines, not failures introduced by this docs PR and -not waivers. No runtime/scaffold E2E was run because this RFC changes no framework or generated -source; the RFC assigns the full one-pass runtime gate to implementation merge readiness. - -## Board Reconciliation Proposal - -No issue or milestone was mutated. After RFC acceptance, the maintainer/root orchestrator should: - -1. reconcile #1348 acceptance with the narrow header/context/cache law; -2. narrow #1349 to descriptor, composer, context/query propagation, and cache safety; -3. keep #1350 as exact base error-map plus metadata repair; -4. keep #1351 as SDK-owned transport consolidation and, only after a separate low-risk decision, an - exact-family stable-v1.15.0 update; do not put v2 in RFC-A; -5. place bearer convention, redaction, and auth delivery under #1352; -6. re-scope #1353 from a trace contribution to trace ownership/reserved-header conformance; -7. file the locale proof child only after acceptance; -8. cross-link generic discovery #1093; -9. keep custom link #451 and later #928/#934/#884 work independent except for shared vocabulary; and -10. propose a separate oRPC v2 migration RFC/spike after RFC-A review, without filing it in this - run. It owns stable/beta policy, atomic exact-family versions, coordinated/parallel endpoints, - route/meta/OpenAPI/Scalar, errors/status, middleware counts, GET/CSRF, OTel topology, desktop - serialization, SSE/streams, query/cache safety, runtime matrix, full CLI/scaffold E2E, docs, and - publish dry-run. - -## Exact Fable Reviewer Instructions - -Use the already-existing Claude Fable 5 session reserved by the root orchestrator. Do not launch a -new authoring or evaluator session from this branch. - +| Gate | Evidence | +| ------------------------------ | ---------------------------------------------------------------------- | +| Real-surface type fixture | PASS — Deno check exit 0; 0.92 s/268,448 KiB informational observation | +| Targeted format/lint | PASS — 9 files checked; fixture lint 1 file/0 findings | +| Focused RFC links | PASS — 1 document, 0 broken links/anchors | +| Repository docs links/accuracy | PASS — 102 documents/0 broken; accuracy PASS | +| Doctrine | PASS — `deno task arch:check` exit 0; warning-only baseline unchanged | +| Diff hygiene | PASS — `git diff --check` | +| Review threads | `VALIDATION_PENDING` | +| Git/PR metadata | `VALIDATION_PENDING` | + +No CLI/scaffold runtime E2E is appropriate for this RFC-only change; implementation stages retain +the full runtime gates. Existing JSR/doc-lint baselines remain recorded in `research.md` and are not +waived. + +## Board-Stage Reconciliation Proposal + +No issue or milestone was mutated. After acceptance, maintainers should: + +1. keep #1348 as the RFC/tracking record and narrow #1349 to the descriptor, composer, + client/query/key/cache seam, private adapters, reconnect law, and Desktop rejection; +2. keep #1350's filed `safe()` error repair as Stage 1a, then explicitly widen it or assign a + dependent Stage 1b owner for `NetScriptProcedureMeta` before auth dogfood; +3. keep #1351 on transport consolidation, lock-only whole-family stable-v1.15.0 decision, unary/ + reconnect/dedupe conformance, and v1 OTel package selection—never v2 migration; +4. keep #1352 on auth-core bearer/redaction/delivery and re-scope #1353 to final trace ownership; +5. file the locale proof child only after RFC acceptance, cross-link #1093, and leave #451 as the + sole custom-link issue; and +6. propose a separate v2 RFC/spike only after RFC-A review. It must gate stable-dist-tag policy, + atomic exact-family versions, coordinated or parallel endpoints, route/meta/OpenAPI/Scalar + parity, error semantic/status parity, middleware counts, replacement method inference, + `allowMethods`/GET/POST/CSRF law, dedupe effectiveness, OTel topology/no double spans, Desktop + MessagePort serializer parity, SSE/stream reconnect credentials, query/cache partitions, + Deno/browser/server matrix, package checks, CLI/scaffold E2E, docs snippets, and publish dry-run. + +## Exact Fable Cycle-2 Instructions + +Use the existing owner-designated Claude Fable 5 evaluator session; do not launch a new evaluator. Read in this order: -1. `.llm/tmp/orpc-v2-audit-followup.md` as the root-requested research amendment input; -2. `rfcs/0000-sdk-client-contributions.md`; -3. `research.md`, especially the proposal challenge, current API evidence, board state, upstream - sources, type probe, and JSR consequences; -4. `plan.md`, including the locked decisions, risks, Plan Gate self-audit, and issue map; -5. `worklog.md` `## Design` and exact gate table; -6. `drift.md`; and -7. the carried proposal at - `/home/codex/repos/netscript-fable5-remediation-plan/.llm/runs/plan-fable5-remediation-roadmap--seed/fable-5-remediation-plan/rfcs/RFC-A-sdk-client-composition.md`. - -Perform a cross-RFC Plan & Design review, not implementation. Specifically try to falsify: - -- minimality against current oRPC/NetScript seams; -- tuple inference and widened/runtime validation at the stated budgets; -- order independence and duplicate/reserved ownership law; -- auth and locale cache isolation across direct, server-query, and TanStack paths; -- redaction, cleartext, redirect, abort, and retry guarantees; -- transport/final-trace ownership and #451 separation; -- static plugin availability versus explicit activation; -- compatibility, JSR declaration boundaries, staged issue ownership, and executable gates; -- upstream-major neutrality and the sufficiency of the three internal adapter ports; -- prepare-once correctness under actual stable-v1 retry behavior, including wrapper versus memo; -- procedure metadata and incoming server request-header direct-call behavior; and -- the boundary and complete gate set for the separate v2 migration, especially GET/CSRF, - mixed-version endpoints, and OTel span ownership. - -For every finding, cite an RFC heading and repository/upstream evidence, classify it as blocking or -FCP-safe, and state the smallest correction. Explicitly say whether both auth and locale can be -implemented without adding a parallel framework. Record the observed reviewer identity, verdict, and -required RFC edits in the harness artifacts and a structured PR comment. Do not assign an RFC -number, implement package code, merge, close/create issues, mutate milestones, or move the PR past -the review lifecycle on the generator's behalf. - -After Fable findings are reconciled, the root orchestrator—not this generator—should run the planned -Qwen adversarial pass against the revised RFC and the Fable verdict. +1. `.llm/runs/docs-rfc-sdk-client-contribution--rfc/plan-eval.md` completely; +2. `rfcs/0000-sdk-client-contributions.md` at the reviewable remediation commit above; +3. `packages/sdk/tests/type-fixtures/sdk-client-contributions-rfc_type.ts`; +4. `research.md` section “Formal PLAN-EVAL cycle 1 amendment”; +5. `plan.md`, especially locked decisions, validation plan, and board stages; +6. `worklog.md` `## Design`, decisions, drift, and exact gate table; +7. `drift.md` cycle-1 entry; and +8. this handoff. + +Re-evaluate each F-A1 through F-A10 individually and record PASS/remaining smallest correction with +an RFC heading and repository/upstream evidence. In particular, verify the scoped declaration gate, +all server/cache key paths and defaults, stream credential refresh, Desktop rejection, private-port +absence, contribution context projection/private channel, corrected v2 GET direction and complete +spike gates, in-tree inference evidence, and #1350 Stage 1a/1b reconciliation. Confirm whether the +plan is now implementable without guessing and whether auth plus locale still require no parallel +framework. + +Do not assign an RFC number, implement framework code, merge, create/close issues, mutate +milestones, start Qwen, or advance the PR beyond the lifecycle authorized by the root orchestrator. diff --git a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/plan.md b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/plan.md index 5096886e4f..1e001ef3f7 100644 --- a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/plan.md +++ b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/plan.md @@ -6,7 +6,7 @@ | -------------- | ------------------------------------------------------------------------------------------------------------ | | Run ID | `docs-rfc-sdk-client-contribution--rfc` | | Branch | `docs/rfc-sdk-client-contribution` | -| Phase | `plan-eval`; owner-directed external review is the next action | +| Phase | `plan-eval`; formal cycle-1 remediation complete, owner-directed cycle-2 re-evaluation is next | | Target | `rfcs/0000-sdk-client-contributions.md` plus mandatory harness artifacts | | Archetype | `2 Integration`; `4 Public DSL / Builder`; `5 Plugin`; `6 CLI / Tooling` (described implementation surfaces) | | Scope overlays | `SCOPE-docs` | @@ -57,31 +57,39 @@ axis, grounded in the current repository and public upstream oRPC behavior. - Current oRPC lock/stable state and an explicit inference ceiling. - Post-generator v2 audit: incompatible wire major, retry callback lifecycle, metadata API change, incoming request-header companion boundary, and the broad migration blast radius. +- Formal PLAN-EVAL cycle 1: scoped declaration gates, complete server key algebra, exhaustive public + generic defaults, stream reconnect epochs, Desktop rejection, exact private-port + placement/absence, contributor-visible context ownership, corrected v2 GET direction, an in-tree + inference fixture, and live #1350 stage ownership. ## Locked Decisions -| Axis | Decision | -| ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Extension axis | Request-header preparation from typed per-call context only. | -| Public protocol | Package-owned `{ family: 'netscript.sdk-client', major: 1 }`, named id, runtime context declaration, owned header names, mandatory response-cache effect, async `prepare`. | -| Context inference | Literal tuple intersection; required properties make request context required; named static conflicts plus runtime validation. | -| Ordering | Sequential deterministic evaluation of the same snapshot; contributors cannot observe accumulated output; valid results commute. | -| Conflict policy | Duplicate id/context/header or reserved/undeclared header is an error; never last-writer-wins. | -| Cache safety | `invariant`, synchronous non-secret `partitioned`, or `direct-only`; direct-only services have no generated query maps. | -| Auth | First-party bearer factory in auth core; per-call async resolver; unmarked metadata defaults to `none`; redacted stable failures. | -| Second consumer | Locale/`accept-language`, proving optional context and partitioned representation outside auth. | -| Metadata | `NetScriptProcedureMeta.access.authentication = "none" \| "optional" \| "required"`; unmarked procedures default to `"none"`. | -| Trace | Transport-owned and reserved; #1353 becomes trace-ownership conformance rather than a contribution. | -| Transport | Discovery/codec/fetch/retry/dedupe/trace/error remain SDK-owned; raw oRPC callbacks and links are not descriptor fields. #451 stays separate. | -| Adapter ports | Three package-private NetScript responsibilities: procedure metadata, prepared outbound headers, and transport policy. Version-specific wiring is non-normative. | -| Retry lifecycle | Prepare exactly once per logical call above retries; immutable prepared header/context output is replayed byte-equivalently on every attempt. | -| Upstream major | Public/generated declarations contain zero raw oRPC symbols. Implement against stable v1; v1.15.0 sequencing is separate; v2 requires a separate RFC/spike. | -| Server companion | Incoming request-header handler is optional and separate; direct calls may have no request headers. It is not outbound contribution composition. | -| Query policy | No arbitrary defaults/invalidation callbacks; only canonical full-key partition suffix and context propagation. | -| Plugin discovery | Optional static module/export/target references; installation exposes availability, explicit generated config activates per service. | -| Inference budget | 16 contributions/service, 8 context keys/contributor, 16 header keys/contributor; type proof recorded. | -| Compatibility | Omitted tuple exactly preserves behavior/key shapes; old generic defaults remain; no-op `port`/`timeout` are deprecated but not removed here. | -| Error ownership | Stable local preparation error, not a server-defined error-map member. | +| Axis | Decision | +| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Extension axis | Request-header preparation from typed per-call context only. | +| Public protocol | Package-owned `{ family: 'netscript.sdk-client', major: 1 }`, named id, runtime context declaration, owned header names, mandatory response-cache effect, async `prepare`. | +| Context inference | Literal tuple intersection; required properties make request context required; named static conflicts plus runtime validation. | +| Ordering | Sequential deterministic evaluation of the same snapshot; contributors cannot observe accumulated output; valid results commute. | +| Conflict policy | Duplicate id/context/header or reserved/undeclared header is an error; never last-writer-wins. | +| Cache safety | `invariant`, synchronous non-secret `partitioned`, or `direct-only`; direct-only services have no generated query maps. | +| Auth | First-party bearer factory in auth core; per-call async resolver; unmarked metadata defaults to `none`; redacted stable failures. | +| Second consumer | Locale/`accept-language`, proving optional context and partitioned representation outside auth. | +| Metadata | `NetScriptProcedureMeta.access.authentication = "none" \| "optional" \| "required"`; unmarked procedures default to `"none"`. | +| Trace | Transport-owned and reserved; #1353 becomes trace-ownership conformance rather than a contribution. | +| Transport | Discovery/codec/fetch/retry/dedupe/trace/error remain SDK-owned; raw oRPC callbacks and links are not descriptor fields. #451 stays separate. | +| Adapter ports | Three package-private NetScript responsibilities: procedure metadata, prepared outbound headers, and transport policy. Version-specific wiring is non-normative. | +| Retry lifecycle | Prepare once per unary logical-call epoch above retries; iterator-phase reconnect starts a fresh epoch and prepares fresh credentials once for that reconnect sequence. | +| Context boundary | Contributors see only their NetScript-owned declared-context projection plus a separate signal; retry/cache/trace/dedupe fields and the private prepared-call channel stay transport-owned. | +| Private ports | The three adapter ports live only under `packages/sdk/src/internal/client-contributions/`, with no barrel or export; doc and packed-consumer negative tests prove absence. | +| Desktop | RFC-A v1 is HTTP-only. MessagePort Desktop clients do not accept contributions; types, construction, and generation reject attempted selection rather than ignoring it. | +| Upstream major | New RFC-A protocol nodes and generated client declarations contain zero raw oRPC symbols under a named non-growing #1350/#1278 baseline. Implement against stable v1; v2 requires a separate RFC/spike. | +| Server companion | Incoming request-header handler is optional and separate; direct calls may have no request headers. It is not outbound contribution composition. | +| Query policy | No arbitrary defaults/invalidation callbacks; only canonical full-key partition suffix and context propagation. | +| Server key law | Default server keys remain exact three-tuples; partitioned keys append `['$netscript.sdk-context', serializedPairs]` as an exact five-tuple across factories, bridge, persister, and collections. | +| Plugin discovery | Optional static module/export/target references; installation exposes availability, explicit generated config activates per service. | +| Inference budget | 16 contributions/service, 8 context keys/contributor, 16 header keys/contributor; type proof recorded. | +| Compatibility | Omitted tuple exactly preserves behavior/key shapes; every widened public generic has an explicit old-shape default; no-op `port`/`timeout` are deprecated but not removed here. | +| Error ownership | Stable local preparation error, not a server-defined error-map member. | ## Open-Decision Sweep @@ -91,18 +99,24 @@ Every brief-named implementation fork is resolved in the RFC. Remaining question 2. server credential convenience export timing; 3. independent #451 scheduling; 4. semantic-preserving public naming refinements; -5. outer wrapper versus immutable per-call memoization for the locked prepare-once invariant; +5. outer wrapper versus immutable per-unary-call memoization, provided the private channel and fresh + iterator-reconnect epoch law remain fixed; 6. procedure-auth metadata ratification placement and incoming server-plugin default behavior; -7. v1.15.0 sequencing; and -8. questions owned by the separate v2 RFC: GET/CSRF, mixed-version endpoint strategy, and OTel - injection ownership. +7. lock-only stable-v1.15.0 sequencing; and +8. questions owned by the separate v2 RFC: preserve current GET with replacement inference and + `allowMethods`/CSRF law versus retire GET and replace dedupe, mixed-version endpoint strategy, + and OTel injection ownership. ## Risk Register | Risk | Mitigation / RFC gate | | ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- | -| Parallel abstraction or upstream leakage | Three NetScript internal ports; zero raw oRPC symbols in public/generated declarations; doc-lint and declaration inspection. | -| Retry refresh within one call | Prepare-once above retry or immutable per-call memo; forced retry gate asserts count 1 and byte-equivalent output. | +| Parallel abstraction or upstream leakage | Three internal ports at one named private path; scoped new/generated declaration scans plus packed negative imports. | +| Frozen unary retry credential | Prepare once above retry or immutable per-call memo; forced `context.retry: 1` gate asserts count 1 and byte-equivalent output. | +| Frozen stream credential | Iterator-phase reconnect is a new epoch; fixture changes the resolver token and requires prepare count 2 across two epochs. | +| Context semantics leak upstream policy | Contributors see only declared context plus signal; retry/cache/trace fields and dedupe replacement remain transport-private. | +| Server key compatibility | Exact default 3-tuple and partitioned 5-tuple tests across six server/cache surfaces and recursive TanStack wrapper fixtures. | +| Desktop silently omits auth | HTTP-only scope with compile/construction/generator rejection and explicit auth/desktop documentation. | | Accidental v2 beta migration | Stable-v1 implementation boundary; separately owned v2 RFC/spike and atomic rollout/parity gate set. | | Tuple/context inference cost | Per-service tail recursion, 16 limit, named markers, type fixtures at 16/17. | | Auth special case | Locale consumer and generic header/context/cache law; auth factory is one constrained implementation. | @@ -134,10 +148,13 @@ Every brief-named implementation fork is resolved in the RFC. Remaining question ### Runtime second 1. Construction validation and reserved ownership. -2. Three internal ports and per-logical-call preparation above retry semantics; stable-v1 adapter - consumes only an immutable prepared record. -3. Canonical cache partitions/direct-only map omission. +2. Three internal ports at `src/internal/client-contributions/`; stable-v1 consumes only a private + immutable prepared-call record and exposes contributors only to the declared-context projection. +3. Canonical cache partitions/direct-only map omission, exact default 3-tuple/partitioned 5-tuple + server keys, and recursive TanStack option wrapping. 4. Redacted errors, abort/retry behavior, and transport integration. +5. Unary retry replays one prepared record; iterator reconnect opens a new preparation epoch. +6. Desktop MessagePort clients reject contribution selection. ### Delivery third @@ -153,14 +170,17 @@ The RFC contains the full future gate matrix. This docs PR runs: - focused RFC internal-link/path validation; - repository docs links and accuracy; - source/API/export and live-board alignment review; -- non-product type probe; +- committed compile-only real-surface type fixture; - current package JSR/doc-lint baseline scan; - doctrine check and PR metadata/thread readiness where applicable. Framework implementation issues inherit type, runtime, redaction, cache isolation, plugin parity, JSR/publish/consumer, CLI/scaffold, architecture, and full runtime E2E gates enumerated in the RFC. -They also inherit the zero-oRPC-symbol declaration scan and stable-v1 adapter conformance. A later -v2 spike repeats that suite plus its separate rollout/error/OTel/route/serializer/streaming gates. +They also inherit the scoped zero-oRPC-symbol declaration scan, private-port absence checks, and +stable-v1 adapter conformance. A later v2 spike repeats that suite plus its separate atomic-family, +route/meta/OpenAPI/Scalar, error/status, execution-count, GET/CSRF/method-inference, dedupe, +OTel-topology, Desktop serializer, SSE/reconnect, query/cache, runtime-matrix, CLI/scaffold, docs, +and publish gates. ## Arch-Debt Implications @@ -170,31 +190,34 @@ unavoidable new deviation requires a debt entry with owner/exit criteria in its ## Validation Plan -| Order | Gate | Command/check | Expected result | -| ----- | -------------------- | ----------------------------------------------------------- | ------------------------------------------------------------------------------------- | -| 1 | Source/API alignment | `deno doc`, focused source/tests/exports, live GitHub reads | All prescriptive claims grounded. | -| 2 | Type ergonomics | ignored `.llm/tmp/` Deno type proof | Valid 16 tuple and required context pass; conflicts/17 fail under `@ts-expect-error`. | -| 3 | RFC integrity | `deno fmt --check`; focused link checker | Exit 0. | -| 4 | Repository docs | `deno task docs:links`; `deno task docs:accuracy` | Exit 0. | -| 5 | Publish consequences | package audit + structured doc-lint on four roots | Baseline recorded; no RFC source mutation. | -| 6 | Doctrine | `deno task arch:check` | Exit 0 or exact unrelated baseline recorded. | -| 7 | GitHub readiness | draft/labels/body/thread/commit verification | Required labels, one status, no milestone mutation/closing keyword. | +| Order | Gate | Command/check | Expected result | +| ----- | -------------------- | ------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------- | +| 1 | Source/API alignment | `deno doc`, focused source/tests/exports, live GitHub reads | All prescriptive claims grounded. | +| 2 | Type ergonomics | `deno check --unstable-kv packages/sdk/tests/type-fixtures/sdk-client-contributions-rfc_type.ts` | Real contract/client/query/key defaults pass; valid 16 passes and conflicts/17 fail under `@ts-expect-error`. | +| 3 | RFC integrity | `deno fmt --check`; focused link checker | Exit 0. | +| 4 | Repository docs | `deno task docs:links`; `deno task docs:accuracy` | Exit 0. | +| 5 | Publish consequences | package audit + structured doc-lint on four roots | Baseline recorded; no RFC source mutation. | +| 6 | Doctrine | `deno task arch:check` | Exit 0 or exact unrelated baseline recorded. | +| 7 | GitHub readiness | draft/labels/body/thread/commit verification | Required labels, one status, no milestone mutation/closing keyword. | ## Plan Gate Self-Audit -The amended RFC plan is ready for external evaluation: it states the current implementation and gap, -compares the broad proposal with existing stable-v1 evidence and narrower alternatives, locks public -placement and composition/failure/security laws, names migration and compatibility behavior, maps -implementation slices and issues, and defines executable fitness gates. The RFC carries no product -implementation. The post-generator oRPC audit amendment fixes upstream-major neutrality and retry -lifecycle before exposing its implementation/sequencing questions to Fable. This is a generator -self-audit and root-requested research amendment, not a PLAN-EVAL verdict; the owner-designated -external reviewer remains authoritative. +The cycle-1-remediated RFC plan is ready for external re-evaluation: it states the current +implementation and gap, compares the broad proposal with existing stable-v1 evidence and narrower +alternatives, locks public placement and composition/failure/security laws, names migration and +compatibility behavior, maps implementation slices and issues, and defines executable fitness gates. +The RFC carries no product implementation. The post-generator oRPC audit amendment first fixed +upstream-major neutrality; the authoritative Fable cycle-1 `FAIL_PLAN` then exposed ten completeness +defects. The RFC now answers each one without changing the core contribution axis. This is author +remediation and a generator self-audit, not a PASS claim; the owner-designated external reviewer +remains authoritative. ## Dependencies and Board Reconciliation - #1348 remains tracking/RFC record. -- #1349–#1352 retain implementation ownership with narrowed bodies. +- #1349 owns the seam/key/adapter implementation; #1350 retains its filed `safe()` error repair as + Stage 1a, while Stage 0 must either explicitly widen it or select a dependent owner for metadata + Stage 1b; #1351–#1352 retain transport and auth ownership. - #1353 is re-scoped to trace transport ownership, not deleted. - A locale proof child is proposed only after acceptance; none is filed in this run. - #1093 supplies generic discovery. @@ -212,8 +235,13 @@ external reviewer remains authoritative. - Any auth helper placed in the thin plugin rather than auth core. - Any trace contributor that can author `traceparent`/`tracestate`. - Any generated activation based only on installation or runtime scanning. -- Any public/generated declaration containing a raw oRPC type, module, callback, context, plugin, - interceptor, or metadata accessor. -- Any adapter that invokes contribution preparation once per retry rather than once per logical - call. +- Any new RFC-A protocol node or generated declaration containing a raw oRPC type, module, callback, + context, plugin, interceptor, or metadata accessor, or any growth in the #1350/#1278 baseline. +- Any adapter that invokes contribution preparation once per ordinary retry, or reuses a credential + across iterator-phase reconnect epochs. +- Any contributor that can observe transport retry/cache/trace/dedupe context or a private prepared + record. +- Any default server key widened from three elements, partitioned key not exactly five elements, or + cache/persister/collection path that loses the canonical suffix. +- Any Desktop target that silently ignores an HTTP contribution. - Any RFC-A implementation PR that bundles an oRPC v2 beta, error/status, or OTel migration. diff --git a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/research.md b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/research.md index a299f16223..ace825477a 100644 --- a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/research.md +++ b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/research.md @@ -46,6 +46,12 @@ - `CreateServiceClientOptions`: 9 fields; no headers/context/link/plugin contribution. - `ServiceClientContext`: signal/cache/retry/trace fields, all optional. - `ServiceClientMethod`: input plus optional `ServiceRequestOptions`. +- `createActionQueryKey()` and `ActionMethod.key`: fixed public three-tuples; `CacheKey` remains + `Deno.KvKey` and server storage prepends `cache_query`. +- `ServiceQueryClientContext`: public `Record`; the checked-in upstream fixture pins + default `ServiceQueryUtils` assignability. +- `@netscript/sdk/desktop`: separate MessagePort client factory with no HTTP header channel or + contribution option. - `ServiceHandlerPlugin`: structural `order`, `init`, and `initRuntimeAdapter` using `unknown`. - `RPCHandlerConfig`: already has `plugins`, tracing/error/dedupe/logging/debug fields. - `PluginContributions`: 10 array groups plus `aspire` and `doctor` module strings; no SDK group. @@ -107,6 +113,26 @@ The amendment locks upstream-major neutrality and three internal NetScript adapt procedure metadata, prepared outbound headers, and transport policy. Stable v1 is the implementation target. A v2 adapter must be designed and gated in a separate RFC/spike. +### Formal PLAN-EVAL cycle 1 amendment + +Claude Fable 5 returned authoritative `FAIL_PLAN / CHANGES_REQUESTED` in `plan-eval.md` at commit +`f1a29fe1a65d59f71a59bf4b6b2a48fc49e1e86f`. The 159-line verdict was read completely; SHA-256 +`0690af2a2914ad0a9118be04ccebb933af33b2bac8f3f743bc7990f8f5f38cdd`. This section is generator +remediation of that verdict, not a self-evaluation. + +| Finding | Re-baselined evidence | Author correction | +| ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| F-A1 | `deno doc --json packages/sdk/src/ports/mod.ts` reaches `~orpc` through current `ContractProcedureLike`/`ContractLike`; doctrine 02 sanctions builder coupling in contracts. | Scope zero-oRPC to named new RFC-A declaration nodes and generated client declarations. Keep a non-growing #1350/#1278 allowlist for unchanged leakage. | +| F-A2 | Server keys are fixed three-tuples in `query-key.ts`/`query-factory.ts`; `CacheKey`, `CacheQuery`, key bridge, KV persister, collections, and the current query-utils cast constrain the design. | Specify exact empty or two-string server suffix, defaulted 3/5 tuple types, six-surface disposition, recursive TanStack wrapping cost, and upstream-fixture disposition. | +| F-A3 | `ServiceClientMethod`, `ServiceClientShape`, `ServiceQueryClientContext`, and query option types are public. | Append a normative compatibility default to every widened public generic; never insert before an existing positional parameter. | +| F-A4 | Locked v1.14.6 resolves headers in codec `encode`; retry re-enters downstream from both unary failure and iterator consumption. | Define stream sessions as multiple preparation epochs: unary retry prepares once, iterator reconnect prepares fresh credentials once per epoch. | +| F-A5 | Desktop creates a second client over MessagePort and has no HTTP header channel. | Keep RFC-A HTTP-only; type/runtime/generator reject Desktop contributions, and auth/desktop docs state the consequence. | +| F-A6 | `src/ports/` is a public barrel. | Place the three ports in `src/internal/client-contributions/`, forbid an internal barrel/export, and add root/subpath doc plus packed-consumer absence gates. | +| F-A7 | Current retry fields hand-copy stable-v1 retry context; retry defaults to zero; dedupe replaces downstream context but keys include headers. | Exclude all transport fields from contribution-visible context, expose signal separately, state the private prepared-call channel, drive retry explicitly, and compare only the prepared projection. | +| F-A8 | Stable v1 enables GET inference now; v2 defaults away from GET, removes `inferRPCMethodFromContractRouter`, and can make GET-only dedupe inert. `@orpc/opentelemetry` also exists on v1. | Correct keep-GET versus retire-GET direction; add inference, allowMethods/CSRF, dedupe-effectiveness, OTel ownership, lock-only family, desktop, and stream gates to the v2 spike. | +| F-A9 | The old `.llm/tmp` proof was ignored and modeled a stripped context. | Commit `packages/sdk/tests/type-fixtures/sdk-client-contributions-rfc_type.ts` against real contract/defineServices/query/key surfaces. | +| F-A10 | Dedupe identity includes headers; v1.15.0 shipped after the then-current v2 beta; #1350 is filed as the `safe()` error repair, not metadata. | Cite verified lifecycle/header safety, classify raw input as sensitive borrowed data, keep stable v1, and split Stage 1a error repair from Stage 1b metadata ownership reconciliation. | + ## Proposal challenge record | Starting proposal choice | Verdict | Reason | @@ -142,11 +168,12 @@ target. A v2 adapter must be designed and gated in a separate RFC/spike. headers are reserved. 9. Plugin manifests carry static module/export/target references; generators use explicit imports and literal tuples. No ambient activation. -10. Public contribution types and generated declarations are upstream-major-neutral and contain zero - raw oRPC symbols. Package-private metadata, prepared-header, and transport-policy ports isolate - version-specific adapters. -11. Preparation runs exactly once per logical call above retry semantics. The immutable prepared - header/context snapshot is reused byte-equivalently on every attempt. +10. Named new RFC-A contribution types and generated client declarations are upstream-major-neutral + and contain zero raw oRPC symbols under the non-growing #1350/#1278 baseline. Package-private + metadata, prepared-header, and transport-policy ports isolate version-specific adapters. +11. Preparation runs exactly once per logical-call epoch above ordinary retry semantics. The + immutable prepared header/context snapshot is reused byte-equivalently on every attempt in that + epoch; iterator reconnect starts a new epoch with fresh preparation. 12. RFC-A implements on stable v1. A v1.15.0 move needs a separate exact-family decision; v2 beta, typed-error/status, OTel, GET/CSRF, protocol rollout, and broad migration work belong to a separate RFC/spike. @@ -154,11 +181,20 @@ target. A v2 adapter must be designed and gated in a separate RFC/spike. ## Type proof -Ignored scratch proof: `.llm/tmp/sdk-client-contribution-probe.ts` with an isolated local config. +Committed compile-only proof: +`packages/sdk/tests/type-fixtures/sdk-client-contributions-rfc_type.ts`. It imports the current real +`ContractLike`, `DefineServiceConfig`/`defineServices`, `ServiceClient`, `ServiceQueryUtils`, and +query-key primitives while modeling only the not-yet-implemented RFC types locally. Checked cases: - required auth plus optional locale context intersection; +- current default client/query/`defineServices` assignability; +- current `ActionMethod`/`QueryFactory` exact three-tuple keys, `FactoryConfig` client default, and + `CacheKey` compatibility; +- contribution-aware `defineServices` client/query results and direct-only omission; +- default three-segment and partitioned five-segment server keys; +- current Desktop options rejecting an HTTP contribution field; - required request argument and missing-auth `@ts-expect-error`; - named duplicate-context conflict at the tuple boundary; - accepted 16-element synthetic tuple; and @@ -167,11 +203,11 @@ Checked cases: Command: ```text -deno check --config .llm/tmp/deno.json .llm/tmp/sdk-client-contribution-probe.ts +deno check --unstable-kv packages/sdk/tests/type-fixtures/sdk-client-contributions-rfc_type.ts ``` -Result: exit 0. The first uncached observation was 0.67 s / 225,508 KiB RSS; a later warm check was -0.02 s / 27,136 KiB. Timing is informational, not a gate. +Result after the cycle-1 remediation: exit 0, 0.92 s elapsed, 268,448 KiB maximum RSS under the +recorded `/usr/bin/time` format. Timing is informational, not a gate. ## JSR / publish-surface audit @@ -204,10 +240,12 @@ than deepen the contract leak. - `@netscript/plugin`: new optional config reference and builder path; no SDK runtime dependency. - `@netscript/plugin-auth-core`: new `./sdk` export and optional explicit `./sdk/server` convenience export; adds a reviewed SDK dependency. -- Generated declarations must remain package-owned and isolated-declaration compatible, with zero - raw oRPC module specifiers or symbols. +- Named new RFC-A declarations and generated client declarations must remain package-owned and + isolated-declaration compatible, with zero raw oRPC module specifiers or symbols. The gate does + not rescan the whole existing ports/contracts graph as if its #1350/#1278 leakage were absent. - Required implementation evidence: `deno doc --lint`, package audit, publish dry-run, packed/prod - consumer check, docs on every new entrypoint, and no `@orpc/*` type in emitted declarations. + consumer check, docs on every new entrypoint, and no `@orpc/*` identity in named new RFC-A or + generated client declarations. ## Remaining safe questions @@ -215,13 +253,13 @@ than deepen the contract leak. - Whether a server environment credential convenience export ships in the first auth slice. - Whether #451 is rescheduled with this work while remaining independent. - Final public naming refinements that preserve the locked semantics. -- Outer wrapper (preferred) versus immutable per-logical-call memoization for stable-v1 - prepare-once. +- Outer wrapper (preferred) versus immutable per-epoch memoization for stable-v1 unary prepare-once; + both must use the specified private channel and re-prepare iterator reconnects. - Whether procedure-auth metadata is ratified inside RFC-A or as a dependent decision implemented through #1350. - Whether the incoming stable-v1 request-header handler is preset-default or explicit, with absent headers supported for direct calls either way. - Whether the stable-v1.15.0 exact-family upgrade precedes or follows the minimal seam. -- For the separate v2 RFC: GET/CSRF law, zero-downtime parallel endpoints versus coordinated - rollout, and whether v2 OTel can replace final injection without violating NetScript span - ownership. +- For the separate v2 RFC: preserve current GET with replacement inference/allowMethods/CSRF or + retire GET and replace dedupe; zero-downtime parallel endpoints versus coordinated rollout; and + whether v2 OTel can replace final injection without violating NetScript span ownership. diff --git a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/supervisor.md b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/supervisor.md index b71e967788..c959fea33c 100644 --- a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/supervisor.md +++ b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/supervisor.md @@ -28,6 +28,10 @@ Written at run start per `workflow/lane-policy.md` § Supervisor identity. - The owner explicitly reserved cross-RFC review for an existing Claude Fable 5 session and a later Qwen adversarial pass. This generator will prepare the artifacts and stop at `status:plan-eval`; it will not trigger PLAN-EVAL or IMPL-EVAL. +- Claude Fable 5 completed formal PLAN-EVAL cycle 1 externally and recorded + `FAIL_PLAN / CHANGES_REQUESTED` in `plan-eval.md`. The owner returned this exact generator thread + for author remediation. This session accepts F-A1–F-A10 as authoritative but does not evaluate its + own corrections; cycle 2 remains on the existing Fable route. - `.llm/tools/agentic/runtime status` reported `MISSING_IDENTITY` because the already-active desktop thread is not registered as a runtime-controller session. The launch-generated `codex-thread-ids.md` and rollout path provide the concrete daemon-attached identity; no daemon @@ -35,13 +39,15 @@ Written at run start per `workflow/lane-policy.md` § Supervisor identity. ## Handoff State -- Generator RFC authorship completed at draft PR #1390; this exact thread then resumed for the - root-requested post-generator oRPC v2 research amendment. +- Generator RFC authorship completed at draft PR #1390; this exact thread resumed first for the + root-requested post-generator oRPC v2 research amendment and now for formal PLAN-EVAL cycle-1 + remediation. - Pre-amendment RFC/research commit: `89ae608ea935ba8b2776d55e7cb5a09cc29e2520`; pre-amendment handoff HEAD: `e78ac0a65f5475ed37152272b16ba7d89deca8c3`. - Reviewable amended RFC/research commit: `7a0d398087a6608ff1a55bb9fe4c47158edb72a7`. -- The amended RFC is returned to `status:plan-eval` only after focused gates, an explicit-refspec - push, and a structured PR phase comment. -- The exact Fable entry point and prohibited mutations are in `final-handoff.md`. -- The amendment is root-requested research, not a formal evaluator verdict. No evaluator was - launched and no external verdict is claimed by this session. +- Formal evaluator artifact: `f1a29fe1a65d59f71a59bf4b6b2a48fc49e1e86f`; verdict SHA-256 + `0690af2a2914ad0a9118be04ccebb933af33b2bac8f3f743bc7990f8f5f38cdd`. +- The remediated RFC returns to `status:plan-eval` only after focused gates, meaningful commits, an + explicit-refspec push, and a structured cycle-2 handoff comment. +- The exact Fable cycle-2 entry point and prohibited mutations are in `final-handoff.md`. No + evaluator was launched and no PASS verdict is claimed by this session. diff --git a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/worklog.md b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/worklog.md index ef963cb63f..33175b8e7c 100644 --- a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/worklog.md +++ b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/worklog.md @@ -25,9 +25,11 @@ future surfaces: - `@netscript/plugin/config`: optional `sdkClients` module reference group. - `@netscript/plugin-auth-core/sdk`: constrained bearer contribution factory. -No new generic transport/plugin/query middleware envelope is authorized. All public and generated -declarations are upstream-major-neutral. Three internal SDK ports isolate procedure metadata, -prepared outbound headers, and transport policy; none is a public export. +No new generic transport/plugin/query middleware envelope is authorized. Named new RFC-A protocol +nodes and all generated client declarations are upstream-major-neutral under a non-growing +#1350/#1278 baseline for existing contract leakage. Three internal SDK ports isolate procedure +metadata, prepared outbound headers, and transport policy under +`packages/sdk/src/internal/client-contributions/`; none has a barrel or public export. ### Domain Vocabulary @@ -38,9 +40,11 @@ prepared outbound headers, and transport policy; none is a public export. - **Response-cache effect** — `invariant`, `partitioned`, or `direct-only` safety declaration. - **Partition** — synchronous, stable, non-secret full-key discriminator visible in cache tools. - **Transport policy** — SDK-owned discovery/codec/fetch/retry/dedupe/trace/dispatch. -- **Logical call** — one user invocation including all transport retry attempts. -- **Prepared call** — one immutable contributor header/context snapshot reused across those - attempts. +- **Logical call epoch** — one ordinary invocation/stream connection sequence including its + transport retry attempts; iterator-phase reconnect starts a new epoch. +- **Stream session** — a user-visible iterator that may contain multiple reconnect epochs. +- **Prepared call** — one immutable contributor header/context projection reused across the ordinary + retry attempts of one epoch. ### Composition Law @@ -50,10 +54,13 @@ prepared outbound headers, and transport policy; none is a public export. 3. Calls execute contributors sequentially in tuple order with the same snapshot. 4. Contributors never observe accumulated results; valid disjoint patches commute. 5. Tuple order affects only deterministic first-error reporting. -6. The prepared-header port runs exactly once per logical call and creates an immutable prepared - call. -7. The transport-policy port receives only that prepared call; each retry reuses byte-equivalent - contributor headers/context, then transport adds base content type and final trace fields. +6. The prepared-header port runs exactly once per logical call epoch and creates an immutable + prepared call. +7. The transport-policy port receives only that prepared call; each ordinary retry reuses + byte-equivalent contributor headers/context, then transport adds base content type and final + trace fields. +8. Iterator-phase stream reconnect begins a new epoch and re-runs preparation exactly once, so a + refreshed credential is visible to every retry in that reconnect sequence. ### Context and Query Law @@ -61,6 +68,10 @@ prepared outbound headers, and transport policy; none is a public export. - Context is threaded through direct, server-query, and TanStack paths. - Context/input/credentials never enter query keys. - `partitioned` values add an id-sorted suffix to full keys only. +- Server defaults remain exact three-tuples; a partition suffix is exactly + `['$netscript.sdk-context', serializedPairs]`, producing an exact five-tuple. Action/query + factories, `CacheKey`/`CacheQuery`, the key bridge, KV persister, collections, and TanStack + wrappers preserve the same algebra. - `direct-only` service keys are absent from generated query/query-utils maps. - No contribution may author query defaults, callbacks, or arbitrary key fragments. - This law survives upstream majors; official v2 TanStack integration still excludes client context @@ -71,16 +82,25 @@ prepared outbound headers, and transport policy; none is a public export. - Stable v1 supplies the first private adapter; RFC-A does not expose or normatively depend on its link/header/context/metadata types. - Internal `ProcedureMetadataPort`, `PreparedOutboundHeadersPort`, and `ClientTransportPolicyPort` - responsibilities are normative; upstream wiring is not. -- Prepare-once is above retries. An outer wrapper is preferred; immutable per-logical-call - memoization is conforming. Direct unmemoized link-header preparation is not. + responsibilities are normative; upstream wiring is not. They live only in + `src/internal/client-contributions/{adapter-ports,prepared-call,stable-v1-adapter}.ts` and must be + absent from root/client/ports/desktop docs and packed imports. +- Contributors see only the declared-context projection plus a separate abort signal. SDK + retry/cache/trace/dedupe context and the private prepared-call symbol/object are not visible. +- Prepare-once is above ordinary retries. An outer wrapper is preferred; immutable per-epoch + memoization is conforming. Direct unmemoized link-header preparation is not. Stream reconnect + starts a fresh epoch rather than replaying indefinitely with an old credential. - The internal `ClientLinkPort` is evidence for #451; it is not exposed by this RFC. - `RPCHandlerConfig.plugins` remains the separate server plugin axis. - `RequestHeadersHandlerPlugin` is only an optional incoming server companion; direct calls may have no request headers. +- RFC-A v1 is HTTP-only. Desktop MessagePort options do not gain contributions; type, runtime, and + generator paths reject attempted HTTP contribution selection with a stable unsupported-transport + error rather than silently omitting auth. - Trace propagation is transport-owned; `traceparent`/`tracestate` are reserved. -- oRPC v2 beta, typed-error/status, GET/CSRF, OpenTelemetry, and coordinated protocol migration are - separately owned RFC/spike scope. +- oRPC v2 beta, typed-error/status, coordinated protocol migration, and OTel topology are separate + RFC/spike scope. Stable v1 already infers GET; the v2 spike must either reimplement inference and + configure `allowMethods`/CSRF or retire GET and replace the GET-only dedupe policy. ### Security and Failure @@ -120,12 +140,13 @@ fluent builders, and global registries. ### Commit Slices -| # | Slice | Gate | Files | -| - | -------------------------------------------- | ------------------------------------------------ | --------------------------------------------- | -| 1 | Activate run identity and evidence skeleton | identity/path review + git status | run bootstrap artifacts | -| 2 | Lock research and author the RFC | source/API citations + type proof + formatting | RFC plus research/design artifacts | -| 3 | Prove docs/JSR/GitHub readiness and hand off | docs/RFC/doctrine gates + live PR reconciliation | final artifact updates and `final-handoff.md` | -| 4 | Reconcile root oRPC v2 audit amendment | primary-source audit + repeated docs/PR gates | RFC and every mandatory handoff artifact | +| # | Slice | Gate | Files | +| - | -------------------------------------------- | ----------------------------------------------------- | -------------------------------------------------- | +| 1 | Activate run identity and evidence skeleton | identity/path review + git status | run bootstrap artifacts | +| 2 | Lock research and author the RFC | source/API citations + type proof + formatting | RFC plus research/design artifacts | +| 3 | Prove docs/JSR/GitHub readiness and hand off | docs/RFC/doctrine gates + live PR reconciliation | final artifact updates and `final-handoff.md` | +| 4 | Reconcile root oRPC v2 audit amendment | primary-source audit + repeated docs/PR gates | RFC and every mandatory handoff artifact | +| 5 | Resolve formal PLAN-EVAL cycle-1 findings | real-surface type fixture + docs/type/link/diff gates | RFC, fixture, and every mandatory handoff artifact | ### Deferred Scope @@ -166,24 +187,37 @@ considered complete. | 2026-08-08 | 4 | design amendment | Locked zero-oRPC public declarations, three internal ports, prepare-once retry law, stable-v1 implementation, and separate v2 RFC/spike gates. | | 2026-08-08 | 4 | focused validation | Re-ran eight-file format, RFC/repository links, docs accuracy, type proof, doctrine, and diff hygiene; all verdict commands exit 0. | | 2026-08-08 | 4 | amendment commit | Committed the reviewable RFC/research amendment as `7a0d398087a6608ff1a55bb9fe4c47158edb72a7`; handoff-only commit and explicit-refspec push remain. | +| 2026-08-08 | 5 | verdict intake | Read authoritative 159-line `plan-eval.md` completely; verified SHA-256 `0690af2a2914ad0a9118be04ccebb933af33b2bac8f3f743bc7990f8f5f38cdd`; accepted F-A1–F-A10 without claiming PASS. | +| 2026-08-08 | 5 | source re-baseline | Rechecked current client/query/cache/Desktop surfaces plus locked stable-v1 retry/dedupe behavior; confirmed each Fable evidence claim and the six hidden decisions. | +| 2026-08-08 | 5 | type fixture | Added the in-tree compile-only real-surface fixture covering current defaults, contract recursion, contribution-aware results, exact 3/5 server keys, conflicts, and 16/17 limits. | +| 2026-08-08 | 5 | design remediation | Scoped the zero-upstream gate; completed key/default/reconnect/Desktop/private-port/context laws; corrected v2 GET/OTel/lock gates; reconciled #1350 Stage 1a versus metadata Stage 1b. | +| 2026-08-08 | 5 | focused validation | Targeted Markdown/TypeScript format, fixture lint/check, focused and 102-document links, docs accuracy, doctrine, and diff hygiene all exit 0; warning-only doctrine/dependency baseline is unchanged. | ## Decisions -| Decision | Reason | Source | -| ------------------------------------------ | -------------------------------------------------------------------------------------- | ------------------------------------------- | -| Treat RFC authorship as Plan & Design. | Deliverable is ratifiable architecture; product code is forbidden. | RFC process, brief, harness run loop | -| Use Archetypes 2/4/5/6 plus `SCOPE-docs`. | Current assigned profiles of described implementation surfaces. | doctrine 06/11, harness profiles | -| Do not launch/repair a session. | Existing thread is proven; owner forbids rival authorship. | `codex-thread-ids.md`, WSL skill | -| Narrow to header preparation. | Existing native async seam covers both consumers; other fields have different owners. | SDK source, oRPC declarations/docs, A11/A14 | -| Make valid composition order-independent. | Doctrine forbids semantic plugin-order dependence; exclusive keys make it enforceable. | doctrine extension-axis law | -| Add mandatory cache effect. | Context/header variants can otherwise collide in current query keys. | query source and upstream query types | -| Keep trace transport-owned. | Client span is created at fetch dispatch; earlier trace header is wrong/overwritten. | `http-client-link.ts`, W3C Trace Context | -| Put bearer factory in auth core. | Convention-bearing primitive belongs in core; plugin stays thin. | doctrine 11 | -| Keep errors separate from contract errors. | Preparation precedes any server response. | failure taxonomy, #1350 boundary | -| Keep RFC-A upstream-major-neutral. | v1/v2 wire and metadata/retry facilities differ; public seam must survive both. | official v2 migration, doctrine A14 | -| Implement against stable v1 only. | v2 beta is pre-release and coordinated migration spans at least 60 production files. | releases, repo scan, root audit | -| Prepare once above retries. | Direct link headers can resolve per downstream retry and rotate credentials mid-call. | beta.25 codec/retry source | -| Classify incoming headers separately. | Server request-header plugin is optional and absent for direct calls. | official request-header plugin docs | +| Decision | Reason | Source | +| ------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------- | +| Treat RFC authorship as Plan & Design. | Deliverable is ratifiable architecture; product code is forbidden. | RFC process, brief, harness run loop | +| Use Archetypes 2/4/5/6 plus `SCOPE-docs`. | Current assigned profiles of described implementation surfaces. | doctrine 06/11, harness profiles | +| Do not launch/repair a session. | Existing thread is proven; owner forbids rival authorship. | `codex-thread-ids.md`, WSL skill | +| Narrow to header preparation. | Existing native async seam covers both consumers; other fields have different owners. | SDK source, oRPC declarations/docs, A11/A14 | +| Make valid composition order-independent. | Doctrine forbids semantic plugin-order dependence; exclusive keys make it enforceable. | doctrine extension-axis law | +| Add mandatory cache effect. | Context/header variants can otherwise collide in current query keys. | query source and upstream query types | +| Keep trace transport-owned. | Client span is created at fetch dispatch; earlier trace header is wrong/overwritten. | `http-client-link.ts`, W3C Trace Context | +| Put bearer factory in auth core. | Convention-bearing primitive belongs in core; plugin stays thin. | doctrine 11 | +| Keep errors separate from contract errors. | Preparation precedes any server response. | failure taxonomy, #1350 boundary | +| Keep RFC-A upstream-major-neutral. | v1/v2 wire and metadata/retry facilities differ; public seam must survive both. | official v2 migration, doctrine A14 | +| Implement against stable v1 only. | v2 beta is pre-release and coordinated migration spans at least 60 production files. | releases, repo scan, root audit | +| Prepare once above retries. | Direct link headers can resolve per downstream retry and rotate credentials mid-call. | beta.25 codec/retry source | +| Classify incoming headers separately. | Server request-header plugin is optional and absent for direct calls. | official request-header plugin docs | +| Scope the zero-upstream gate. | Existing `ContractLike`/contracts deliberately contain `~orpc`; only new protocol nodes and generated client declarations can pass zero today. | F-A1, doctrine 02, #1350/#1278 | +| Make server keys exact and compatible. | Current public factory keys are fixed three-tuples; safe partitioning requires a canonical two-slot suffix through every storage path. | F-A2, SDK query/cache source | +| Default every widened public generic. | Omitted contributions must remain source-assignable to the current client/query types. | F-A3, real-surface fixture | +| Refresh credentials on stream reconnect. | Iterator retry occurs after the initial call returns; reusing its preparation can freeze a bearer indefinitely. | F-A4, stable-v1 retry source | +| Reject Desktop contributions. | MessagePort has no HTTP header channel; silent acceptance would falsely imply auth delivery. | F-A5, Desktop source | +| Hide ports at one exact internal path. | `src/ports/` is public; doc and packed-import negative gates must prove the seam stays private. | F-A6, JSR audit | +| Project contributor-visible context. | Retry/cache/trace fields and dedupe replacement are transport semantics, not extension-axis vocabulary. | F-A7, stable-v1 source | +| Correct the v2 GET direction. | v1 enables GET today; v2 rejects it by default and removes the inference helper, potentially making dedupe inert. | F-A8, migration/source audit | ## Drift @@ -195,36 +229,43 @@ considered complete. | Proposal omitted cache identity risk of typed auth/locale context. | significant design drift | yes | | Current package doc-lint/JSR baselines contain pre-existing findings. | baseline | yes | | Original RFC prose treated stable-v1 link headers as the normative lifecycle. | significant design drift | yes | +| Formal PLAN-EVAL cycle 1 found ten decision/gate completeness defects. | authoritative FAIL_PLAN | yes | ## Gate Results -| Gate | Command | Result | -| --------------------- | ----------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | -| RFC format | `deno fmt --check rfcs/0000-sdk-client-contributions.md` | PASS after format | -| Focused RFC links | link checker with `--root rfcs/0000-sdk-client-contributions.md` | PASS, 0 broken links/anchors | -| Repository docs links | `deno task docs:links` | PASS, 102 docs, 0 broken links/anchors | -| Docs accuracy | `deno task docs:accuracy` | PASS | -| Type proof | `deno check --config .llm/tmp/deno.json .llm/tmp/sdk-client-contribution-probe.ts` | PASS | -| Package audit | four `audit-jsr-package.ts --text` runs | contracts/sdk/auth-core exit 0; plugin exit 1 on pre-existing 4 module-tag + cardinality findings; all dry-runs OK | -| Structured doc lint | four `run-deno-doc-lint.ts` runs | baseline private refs: contracts 9, SDK 3, plugin 15, auth-core 4; report command exits 0 | -| Doctrine | `deno task arch:check` | PASS, exit 0; existing warning-only package debt recorded and not waived | -| Plan Gate self-audit | checklist against `plan-gate.md` and RFC required sections | PASS for evaluator entry; not a PLAN-EVAL verdict | -| Diff hygiene | `git diff --check` | PASS | -| PR metadata | live `gh pr view` | PASS: draft/main, required labels, exactly one `status:plan-eval`, milestone null, #1348 reference only | -| Review threads | `deno task agentic:review-threads -- --repo rickylabs/netscript --pr 1390 --pretty` | PASS, 0 threads / 0 unanswered | -| Audit input | `wc -l` and `sha256sum .llm/tmp/orpc-v2-audit-followup.md` | PASS, 59 lines; SHA-256 `fa8b0ab5cd1afd57b8f6c20036a265fa7c8fb48764f88f97f289c44c0737d3d0` | -| oRPC stable channel | `deno task deps:latest --filter '@orpc/*'` | Seven v1.14.x workspace dependencies behind to stable v1.15.0; evidence only, no dependency mutation | -| oRPC impact scan | focused `rg -l '@orpc/' packages plugins` | 91 reference files; 74 after excluding test paths/name patterns | -| Amendment format | `deno fmt --check` on RFC plus seven mandatory handoff artifacts | PASS, eight files | -| Amendment RFC links | focused internal-doc link checker | PASS, 1 document, 0 broken links/anchors | -| Amendment docs | `deno task docs:links`; `deno task docs:accuracy` | PASS, 102 docs/0 broken; accuracy PASS | -| Amendment type proof | ignored exact-shape Deno probe | PASS | -| Amendment doctrine | `deno task arch:check` | PASS, exit 0; warning-only baseline unchanged | - -The root-requested amendment content gates and reviewable commit are complete. The final -explicit-refspec push and live PR reconciliation follow the handoff-only commit, so their exact HEAD -and lifecycle evidence are recorded in the structured PR comment. External Fable/Qwen verdicts -remain pending by owner instruction. +| Gate | Command | Result | +| ----------------------- | ------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------ | +| RFC format | `deno fmt --check rfcs/0000-sdk-client-contributions.md` | PASS after format | +| Focused RFC links | link checker with `--root rfcs/0000-sdk-client-contributions.md` | PASS, 0 broken links/anchors | +| Repository docs links | `deno task docs:links` | PASS, 102 docs, 0 broken links/anchors | +| Docs accuracy | `deno task docs:accuracy` | PASS | +| Original type proof | `deno check --config .llm/tmp/deno.json .llm/tmp/sdk-client-contribution-probe.ts` | Historical PASS; superseded by the committed real-surface fixture | +| Package audit | four `audit-jsr-package.ts --text` runs | contracts/sdk/auth-core exit 0; plugin exit 1 on pre-existing 4 module-tag + cardinality findings; all dry-runs OK | +| Structured doc lint | four `run-deno-doc-lint.ts` runs | baseline private refs: contracts 9, SDK 3, plugin 15, auth-core 4; report command exits 0 | +| Doctrine | `deno task arch:check` | PASS, exit 0; existing warning-only package debt recorded and not waived | +| Plan Gate self-audit | checklist against `plan-gate.md` and RFC required sections | PASS for evaluator entry; not a PLAN-EVAL verdict | +| Diff hygiene | `git diff --check` | PASS | +| PR metadata | live `gh pr view` | PASS: draft/main, required labels, exactly one `status:plan-eval`, milestone null, #1348 reference only | +| Review threads | `deno task agentic:review-threads -- --repo rickylabs/netscript --pr 1390 --pretty` | PASS, 0 threads / 0 unanswered | +| Audit input | `wc -l` and `sha256sum .llm/tmp/orpc-v2-audit-followup.md` | PASS, 59 lines; SHA-256 `fa8b0ab5cd1afd57b8f6c20036a265fa7c8fb48764f88f97f289c44c0737d3d0` | +| oRPC stable channel | `deno task deps:latest --filter '@orpc/*'` | Seven v1.14.x workspace dependencies behind to stable v1.15.0; evidence only, no dependency mutation | +| oRPC impact scan | focused `rg -l '@orpc/' packages plugins` | 91 reference files; 74 after excluding test paths/name patterns | +| Amendment format | `deno fmt --check` on RFC plus seven mandatory handoff artifacts | PASS, eight files | +| Amendment RFC links | focused internal-doc link checker | PASS, 1 document, 0 broken links/anchors | +| Amendment docs | `deno task docs:links`; `deno task docs:accuracy` | PASS, 102 docs/0 broken; accuracy PASS | +| Amendment type proof | ignored exact-shape Deno probe | Historical PASS; superseded by cycle-1 remediation fixture | +| Amendment doctrine | `deno task arch:check` | PASS, exit 0; warning-only baseline unchanged | +| Cycle-1 type fixture | `deno check --unstable-kv packages/sdk/tests/type-fixtures/sdk-client-contributions-rfc_type.ts` | PASS, exit 0; current defaults/contract recursion/3-and-5-key shapes/16-and-17 budget checked | +| Cycle-1 format | `deno fmt --check` on RFC, fixture, and seven author-owned mandatory artifacts | PASS, 9 files checked | +| Cycle-1 fixture lint | scoped `run-deno-lint.ts --file ...sdk-client-contributions-rfc_type.ts` | PASS, 1 file, 0 occurrences | +| Cycle-1 RFC links | focused internal-doc link checker | PASS, 1 document, 0 broken links/anchors | +| Cycle-1 repository docs | `deno task docs:links`; `deno task docs:accuracy` | PASS, 102 docs/0 broken; accuracy PASS | +| Cycle-1 doctrine | `deno task arch:check` | PASS, exit 0; warning-only dependency/doctrine baseline unchanged | +| Cycle-1 diff hygiene | `git diff --check` | PASS | + +Cycle-1 remediation validation, commits, explicit-refspec push, and live PR reconciliation are +recorded below after the verdict commands complete. External Fable cycle 2 and later Qwen verdicts +remain pending by owner instruction; this author does not self-approve or launch them. ## Handoff Notes @@ -237,8 +278,12 @@ External reviewers should attack: 4. whether redaction permits any indirect token/partition leakage or source-error reappearance; and 5. whether plugin availability versus explicit activation is sufficiently concrete for #1093 and generators; -6. whether the internal outer wrapper or memoized realization best proves prepare-once; +6. whether the internal outer wrapper or memoized realization best proves unary prepare-once while a + stream reconnect necessarily starts a fresh preparation epoch; 7. whether auth metadata sits inside RFC-A acceptance or a dependent ratification; 8. whether stable-v1.15.0 should precede the seam and incoming request headers should be preset default; and -9. whether the separate v2 RFC gates GET/CSRF, mixed endpoints, and OTel ownership strongly enough. +9. whether the separate v2 RFC completely gates replacement method inference, `allowMethods`/CSRF, + dedupe effectiveness, mixed endpoints, OTel ownership, Desktop serializers, SSE credential + refresh, cache partitioning, runtime matrices, E2E, docs, and publish proof; and +10. whether each of F-A1 through F-A10 is now resolved without changing the contribution axis. diff --git a/packages/sdk/tests/type-fixtures/sdk-client-contributions-rfc_type.ts b/packages/sdk/tests/type-fixtures/sdk-client-contributions-rfc_type.ts new file mode 100644 index 0000000000..fb2c9fcb8e --- /dev/null +++ b/packages/sdk/tests/type-fixtures/sdk-client-contributions-rfc_type.ts @@ -0,0 +1,503 @@ +/** + * Compile-only RFC-A inference proof against the current SDK contract and query surfaces. + * + * This file deliberately models the proposed types locally. It is not product implementation; + * it keeps the RFC's 16-contribution budget and compatibility claims reproducible in-tree until + * the accepted implementation replaces the local model with public imports. + */ + +import { type DefineServiceConfig, defineServices } from '../../src/presets/define-services.ts'; +import type { + ContractLike, + ContractProcedureLike, + ContractSchema, + ProcedureInputFromNode, + ProcedureOutputFromNode, + ServiceClient, + ServiceClientContext, + ServiceClientContract, +} from '../../src/ports/service-client.ts'; +import type { + ServiceProcedureQueryResult, + ServiceQueryUtils, +} from '../../src/ports/service-query-utils.ts'; +import type { ActionMethod, FactoryConfig, QueryFactory } from '../../src/ports/query-factory.ts'; +import { createActionQueryKey, type QueryKeyPart } from '../../src/ports/query-key.ts'; +import type { CacheKey } from '../../src/ports/cache-store.ts'; +import type { CreateDesktopServiceClientOptions } from '../../src/desktop/domain/types.ts'; + +type Assert = T; +type IsAssignable = [TFrom] extends [TTo] ? true : false; +type StringKey = Extract; +type EmptyContext = Record; + +interface ListOrdersInput { + readonly page: number; +} + +interface ListOrdersOutput { + readonly items: readonly { readonly id: string }[]; +} + +type Schema = ContractSchema & { + readonly '~standard': { + readonly types: { + readonly input: TInput; + readonly output: TOutput; + }; + }; +}; + +type Procedure = ContractProcedureLike< + Schema, + Schema +>; + +declare const serviceContract: { + readonly orders: { + readonly list: Procedure; + }; +}; + +type _RealContract = Assert>; + +type RfcCacheMode = 'invariant' | 'partitioned' | 'direct-only'; + +type RfcContextDeclaration = { + readonly [K in StringKey]-?: EmptyContext extends Pick ? 'optional' + : 'required'; +}; + +interface RfcContribution< + TId extends string = string, + TContext extends object = EmptyContext, + THeaderKeys extends readonly string[] = readonly string[], + TCacheMode extends RfcCacheMode = RfcCacheMode, +> { + /** Compile-only stand-in for the accepted implementation's generic context identity. */ + readonly __context?: TContext; + readonly protocol: { + readonly family: 'netscript.sdk-client'; + readonly major: 1; + }; + readonly id: TId; + readonly context: RfcContextDeclaration; + readonly headerKeys: THeaderKeys; + readonly responseCache: { readonly mode: TCacheMode }; + readonly prepare: (options: { + readonly context: Readonly; + readonly signal?: AbortSignal; + readonly input: unknown; + }) => unknown; +} + +interface AnyRfcContribution { + readonly __context?: object; + readonly protocol: { + readonly family: 'netscript.sdk-client'; + readonly major: 1; + }; + readonly id: string; + readonly context: Readonly>; + readonly headerKeys: readonly string[]; + readonly responseCache: { readonly mode: RfcCacheMode }; +} + +function defineRfcContribution() { + return < + const TId extends string, + const THeaderKeys extends readonly string[], + const TCacheMode extends RfcCacheMode, + >( + contribution: RfcContribution, + ): RfcContribution => contribution; +} + +type RfcIdOf = T extends { readonly id: infer TId extends string } ? TId : never; +type RfcContextOf = T extends { readonly __context?: infer TContext extends object } ? TContext + : never; +type RfcContextKeysOf = StringKey>; +type RfcHeaderKeysOf = T extends { readonly headerKeys: infer TKeys extends readonly string[] } + ? TKeys[number] + : never; + +interface RfcConflict { + readonly __netscriptContributionConflict: `${TKind}:${TKey}`; +} + +type RfcMergeTuple< + TContributions extends readonly AnyRfcContribution[], + TContext extends object = EmptyContext, + TIds extends string = never, + TContextKeys extends string = never, + THeaderKeys extends string = 'content-type' | 'traceparent' | 'tracestate', +> = TContributions extends readonly [ + infer THead extends AnyRfcContribution, + ...infer TTail extends AnyRfcContribution[], +] ? RfcIdOf extends TIds ? RfcConflict<'id', RfcIdOf> + : [Extract, TContextKeys>] extends [never] + ? [Extract, THeaderKeys>] extends [never] ? RfcMergeTuple< + TTail, + TContext & RfcContextOf, + TIds | RfcIdOf, + TContextKeys | RfcContextKeysOf, + THeaderKeys | RfcHeaderKeysOf + > + : RfcConflict<'header', Extract, THeaderKeys>> + : RfcConflict<'context', Extract, TContextKeys>> + : TContext; + +type RfcAtMostSixteen = TContributions extends + readonly [ + AnyRfcContribution, + AnyRfcContribution, + AnyRfcContribution, + AnyRfcContribution, + AnyRfcContribution, + AnyRfcContribution, + AnyRfcContribution, + AnyRfcContribution, + AnyRfcContribution, + AnyRfcContribution, + AnyRfcContribution, + AnyRfcContribution, + AnyRfcContribution, + AnyRfcContribution, + AnyRfcContribution, + AnyRfcContribution, + AnyRfcContribution, + ...AnyRfcContribution[], + ] ? RfcConflict<'limit', 'more-than-16'> + : unknown; + +type RfcValidateTuple = + RfcMergeTuple extends RfcConflict ? RfcMergeTuple + : RfcAtMostSixteen; + +type RfcContributionContext = + RfcMergeTuple extends infer TResult extends object ? TResult : never; + +declare function acceptRfcContributions< + const TContributions extends readonly AnyRfcContribution[], +>( + contributions: TContributions & RfcValidateTuple, +): RfcContributionContext; + +type RequiredKeys = { + [K in keyof TContext]-?: EmptyContext extends Pick ? never : K; +}[keyof TContext]; + +type RfcRequestRest = RequiredKeys extends never + ? [options?: { readonly context?: TContext }] + : [options: { readonly context: TContext }]; + +type RfcServiceClientMethod< + TInput, + TOutput, + TContext extends object = ServiceClientContext, +> = (input: TInput, ...request: RfcRequestRest) => Promise; + +type RfcServiceClientShape< + TContract extends ContractLike, + TContext extends object = ServiceClientContext, +> = TContract extends ContractProcedureLike ? RfcServiceClientMethod< + ProcedureInputFromNode, + ProcedureOutputFromNode, + TContext + > + : { + [K in keyof TContract]: TContract[K] extends ContractLike + ? RfcServiceClient + : never; + }; + +type RfcServiceClient< + TContract extends ContractLike, + TContext extends object = ServiceClientContext, +> = RfcServiceClientShape & ServiceClientContract; + +declare const currentClient: ServiceClient; +const defaultCompatibleClient: RfcServiceClient = currentClient; +void defaultCompatibleClient; + +type RfcProcedureQueryOptions = + & (undefined extends TInput ? { readonly input?: TInput } : { readonly input: TInput }) + & (RequiredKeys extends never ? { readonly context?: TContext } + : { readonly context: TContext }); + +interface RfcContextualProcedureQueryUtils { + readonly call: RfcServiceClientMethod; + queryOptions( + options: RfcProcedureQueryOptions, + ): ServiceProcedureQueryResult; +} + +type RfcServiceQueryUtils< + TContract extends ContractLike, + TContext extends object = EmptyContext, +> = StringKey extends never ? ServiceQueryUtils + : TContract extends ContractProcedureLike ? RfcContextualProcedureQueryUtils< + ProcedureInputFromNode, + ProcedureOutputFromNode, + TContext + > + : { + [K in keyof TContract]: TContract[K] extends ContractLike + ? RfcServiceQueryUtils + : never; + }; + +declare const currentQueryUtils: ServiceQueryUtils; +const defaultCompatibleQueryUtils: RfcServiceQueryUtils = currentQueryUtils; +void defaultCompatibleQueryUtils; + +const currentDefinedServices = defineServices({ + publicCatalog: { contract: serviceContract }, +}); +const currentDefinedQueryUtils: ServiceQueryUtils = + currentDefinedServices.queryUtils.publicCatalog; +void currentDefinedQueryUtils; + +type CurrentOrdersAction = ActionMethod; +type CurrentOrdersFactory = QueryFactory; +type CurrentOrdersFactoryConfig = FactoryConfig; +type _CurrentActionKeyIsExactThreeTuple = Assert< + IsAssignable< + ReturnType, + readonly [string, 'list', string] + > +>; +type _CurrentFactoryKeyIsExactThreeTuple = Assert< + IsAssignable< + ReturnType, + readonly [string, 'list', string] + > +>; +type _CurrentFactoryClientKeepsDefaultContext = Assert< + IsAssignable< + CurrentOrdersFactoryConfig['client'], + ServiceClient + > +>; + +const currentServerKey = createActionQueryKey('orders', 'list', { page: 1 }); +const currentExactServerKey: readonly [string, string, string] = currentServerKey; +void currentExactServerKey; + +type RfcServerKeySuffix = + | readonly [] + | readonly ['$netscript.sdk-context', string]; + +type RfcActionQueryKey< + TAction extends string = string, + TSuffix extends RfcServerKeySuffix = readonly [], +> = readonly [string, TAction, string, ...TSuffix]; + +type _DefaultKeyPartsRemainValid = Assert< + IsAssignable[number], QueryKeyPart> +>; +type _PartitionedServerKeyRemainsCacheKey = Assert< + IsAssignable< + RfcActionQueryKey<'list', readonly ['$netscript.sdk-context', string]>, + CacheKey + > +>; + +const defaultServerKey: RfcActionQueryKey<'list'> = ['orders', 'list', '{"page":1}']; +const partitionedServerKey: RfcActionQueryKey< + 'list', + readonly ['$netscript.sdk-context', string] +> = [ + 'orders', + 'list', + '{"page":1}', + '$netscript.sdk-context', + '[["app:locale","de-CH"]]', +]; +void defaultServerKey; +void partitionedServerKey; + +const auth = defineRfcContribution<{ auth: { readonly token: () => Promise } }>()({ + protocol: { family: 'netscript.sdk-client', major: 1 }, + id: '@netscript/plugin-auth:bearer', + context: { auth: 'required' }, + headerKeys: ['authorization'], + responseCache: { mode: 'partitioned' }, + prepare: ({ context }) => context.auth.token(), +}); + +const locale = defineRfcContribution<{ locale?: string }>()({ + protocol: { family: 'netscript.sdk-client', major: 1 }, + id: 'app:locale', + context: { locale: 'optional' }, + headerKeys: ['accept-language'], + responseCache: { mode: 'partitioned' }, + prepare: ({ context }) => context.locale, +}); + +const directOnly = defineRfcContribution<{ opaqueSession: string }>()({ + protocol: { family: 'netscript.sdk-client', major: 1 }, + id: 'app:opaque-session', + context: { opaqueSession: 'required' }, + headerKeys: ['x-session'], + responseCache: { mode: 'direct-only' }, + prepare: ({ context }) => context.opaqueSession, +}); + +const rejectedDesktopOptions: CreateDesktopServiceClientOptions = { + contract: serviceContract, + // @ts-expect-error RFC-A keeps HTTP contributions off the Desktop MessagePort options surface + contributions: [auth], +}; +void rejectedDesktopOptions; + +acceptRfcContributions([auth, locale]); + +const duplicateAuthContext = defineRfcContribution<{ auth?: { readonly apiKey: string } }>()({ + protocol: { family: 'netscript.sdk-client', major: 1 }, + id: 'app:other-auth', + context: { auth: 'optional' }, + headerKeys: ['x-api-key'], + responseCache: { mode: 'direct-only' }, + prepare: () => undefined, +}); + +// @ts-expect-error duplicate context ownership is rejected at the tuple boundary +acceptRfcContributions([auth, duplicateAuthContext]); + +type RfcDefineServiceConfig< + TContract extends ContractLike, + TContributions extends readonly AnyRfcContribution[] = readonly [], +> = DefineServiceConfig & { + readonly contributions?: TContributions & RfcValidateTuple; +}; + +type RfcContractOf = TConfig extends { + readonly contract: infer TContract extends ContractLike; +} ? TContract + : never; + +type RfcContributionsOf = TConfig extends { + readonly contributions: infer TContributions extends readonly AnyRfcContribution[]; +} ? TContributions + : readonly []; + +type RfcHasDirectOnly = Extract< + TContributions[number]['responseCache'], + { readonly mode: 'direct-only' } +> extends never ? false : true; + +type RfcDefinedQueryContext = RfcContributionsOf extends readonly [] + ? EmptyContext + : ServiceClientContext & RfcContributionContext>; + +type RfcDefinedServices = { + readonly clients: { + readonly [K in keyof TServices]: RfcServiceClient< + RfcContractOf, + ServiceClientContext & RfcContributionContext> + >; + }; + readonly queryUtils: { + readonly [ + K in keyof TServices as RfcHasDirectOnly< + RfcContributionsOf + > extends true ? never : K + ]: RfcServiceQueryUtils< + RfcContractOf, + RfcDefinedQueryContext + >; + }; +}; + +declare function rfcDefineServices< + const TServices extends Record< + string, + RfcDefineServiceConfig + >, +>(services: TServices): RfcDefinedServices; + +const services = rfcDefineServices({ + accounts: { + contract: serviceContract, + contributions: [auth, locale] as const, + }, + publicCatalog: { + contract: serviceContract, + }, + desktopOnly: { + contract: serviceContract, + contributions: [directOnly] as const, + }, +}); + +const unchangedDefinedUtils: ServiceQueryUtils = + services.queryUtils.publicCatalog; +void unchangedDefinedUtils; + +services.clients.accounts.orders.list({ page: 1 }, { + context: { + auth: { token: () => Promise.resolve('secret') }, + locale: 'de-CH', + }, +}); + +// @ts-expect-error required auth context makes the request options mandatory +services.clients.accounts.orders.list({ page: 1 }); + +services.queryUtils.accounts.orders.list.queryOptions({ + input: { page: 1 }, + context: { + auth: { token: () => Promise.resolve('secret') }, + locale: 'de-CH', + }, +}); + +// A context-bearing service uses this distinct generated shape; the implementation fixture must +// construct it through the contribution-aware wrapper rather than extending the default +// upstream-assignability assertion above to this specialization. +declare const contributedQueryUtils: RfcServiceQueryUtils< + typeof serviceContract, + ServiceClientContext & RfcContributionContext +>; +void contributedQueryUtils; + +// @ts-expect-error direct-only services are omitted from the generated query-utils map +services.queryUtils.desktopOnly; + +type SyntheticContribution = RfcContribution< + `app:c${TNumber}`, + Record<`c${TNumber}`, string>, + readonly [`x-c${TNumber}`], + 'invariant' +>; + +type SixteenContributions = readonly [ + SyntheticContribution<'01'>, + SyntheticContribution<'02'>, + SyntheticContribution<'03'>, + SyntheticContribution<'04'>, + SyntheticContribution<'05'>, + SyntheticContribution<'06'>, + SyntheticContribution<'07'>, + SyntheticContribution<'08'>, + SyntheticContribution<'09'>, + SyntheticContribution<'10'>, + SyntheticContribution<'11'>, + SyntheticContribution<'12'>, + SyntheticContribution<'13'>, + SyntheticContribution<'14'>, + SyntheticContribution<'15'>, + SyntheticContribution<'16'>, +]; + +declare const sixteen: SixteenContributions; +acceptRfcContributions(sixteen); + +declare const seventeen: readonly [ + ...SixteenContributions, + SyntheticContribution<'17'>, +]; + +// @ts-expect-error the RFC-A public inference budget is sixteen contributions per service +acceptRfcContributions(seventeen); diff --git a/rfcs/0000-sdk-client-contributions.md b/rfcs/0000-sdk-client-contributions.md index 44b316f38d..4c6a2d882e 100644 --- a/rfcs/0000-sdk-client-contributions.md +++ b/rfcs/0000-sdk-client-contributions.md @@ -20,9 +20,9 @@ serialization, retry, deduplication, tracing, fetch, and transport. Query helper context only when each contribution proves that its response cache is invariant or supplies a synchronous, non-secret partition; otherwise the contributed client is direct-call-only. -The public protocol and generated declarations are upstream-major-neutral: they contain no oRPC -types, links, plugins, contexts, interceptors, or metadata accessors. NetScript-owned internal ports -translate procedure metadata, prepared outbound headers, and transport policy to the supported +The public protocol and generated client declarations are upstream-major-neutral: they contain no +oRPC types, links, plugins, contexts, interceptors, or metadata accessors. NetScript-owned internal +ports translate procedure metadata, prepared outbound headers, and transport policy to the supported adapter. The first implementation targets stable oRPC v1; an oRPC v2 migration is a separate, coordinated RFC/spike. Bearer credentials in `@netscript/plugin-auth-core` are the first dogfood consumer. A locale contribution, which owns `accept-language`, is the required non-auth proof. Trace @@ -97,8 +97,9 @@ This RFC MUST: 7. make contributions statically discoverable but explicitly selected; and 8. retain SDK ownership of the HTTP transport and its observability invariants; 9. keep every public and generated declaration independent of the selected upstream major; and -10. prepare contribution output exactly once per logical call and replay one immutable result across - transport retries. +10. prepare contribution output exactly once per logical call epoch, replay one immutable result + across that epoch's transport retries, and begin a fresh preparation epoch for every + iterator-phase stream reconnect. ### Non-goals @@ -123,8 +124,10 @@ This RFC does not: - **Contribution**: a named, versioned descriptor that owns context keys and possible request header names and prepares a header patch for one call. - **Contribution tuple**: the literal `readonly` tuple explicitly attached to a service client. -- **Preparation snapshot**: the immutable context, procedure descriptor, input, and transport - descriptor passed independently to every contribution. +- **Contribution context projection**: only the keys declared by contributions. SDK transport keys + such as retry, cache, trace, and signal are not part of it; cancellation is exposed separately. +- **Preparation snapshot**: the immutable contribution context projection, signal, procedure + descriptor, input, and transport descriptor passed independently to every contribution. - **Header ownership**: the exclusive right to emit one lower-case request header name. - **Response-cache effect**: the contributor's declaration that its header is response-invariant, partitionable, or unsafe for generated query helpers. @@ -132,10 +135,13 @@ This RFC does not: credential and is intentionally visible in cache tools. - **Transport policy**: discovery, URL/method selection, codec, retry, dedupe, tracing, `fetch`, streaming, and dispatch. The SDK owns it for `createServiceClient()`. -- **Logical call**: one user-visible procedure invocation, including every transport retry required - to produce its final result. -- **Prepared call**: the logical call plus one immutable, validated contributor-header record. Every - retry receives the same prepared contributor output and context snapshot. +- **Logical call epoch**: for a unary call, one user-visible invocation including its transport + retries; for a stream, one connection attempt sequence ending when an iterator is returned or a + reconnect is exhausted. An iterator-phase reconnect starts a new epoch. +- **Stream session**: the user-visible async iterator, which may span multiple logical call epochs. +- **Prepared call**: one logical call epoch plus one immutable, validated contributor-header record. + Every transport attempt in that epoch receives the same prepared contributor output and + contribution context projection. - **Adapter port**: a NetScript-owned, non-exported structural boundary between RFC-A semantics and the selected transport/contract implementation. Upstream-specific adapters implement these ports. @@ -298,9 +304,11 @@ runtime; it is not a property containing `undefined`. ### Async and server-side sources -`prepare` and `resolveCredential` may be async and are invoked exactly once per logical call, before -any transport retry loop. They are never invoked at module import, client construction, or again for -a retry attempt. An application may close over a concurrency-safe rotating credential source: +`prepare` and `resolveCredential` may be async and are invoked exactly once per logical call epoch, +before that epoch's transport retry loop. They are never invoked at module import, client +construction, or again for an ordinary retry attempt. Iterator-phase stream reconnects begin a new +epoch so a rotating credential source is consulted again. An application may close over a +concurrency-safe rotating credential source: ```ts const bearer = createBearerSdkClientContribution({ @@ -386,7 +394,7 @@ const descriptor: SdkClientProcedureDescriptor = { This follows the official [v2 migration from `.$meta` to `defineMeta`](https://v2.orpc.dev/docs/migrations/from-v1#meta-replaced-by-meta-plugins). -Neither adapter form appears in the contribution protocol or generated public source. +Neither adapter form appears in the contribution protocol or generated client public source. ### Public contribution contract @@ -412,8 +420,11 @@ export interface SdkClientTransportDescriptor { readonly secure: boolean; } -export interface SdkClientPrepareOptions { - readonly context: Readonly; +export interface SdkClientPrepareOptions< + TContext extends object = Record, +> { + readonly context: Readonly; + readonly signal?: AbortSignal; readonly procedure: SdkClientProcedureDescriptor; readonly transport: SdkClientTransportDescriptor; readonly input: unknown; @@ -429,8 +440,10 @@ export type SdkClientContextDeclaration = { : 'required'; }; -export interface SdkClientCachePartitionOptions { - readonly context: Readonly; +export interface SdkClientCachePartitionOptions< + TContext extends object = Record, +> { + readonly context: Readonly; readonly procedure: SdkClientProcedureDescriptor; } @@ -463,11 +476,24 @@ export interface SdkClientContribution< } ``` +`context` in `SdkClientPrepareOptions` and `SdkClientCachePartitionOptions` is deliberately the +contribution-owned projection, not `ServiceClientContext & TContext`. The SDK reserves `signal`, +`cache`, `retry`, `retryDelay`, `shouldRetry`, `onRetry`, and `traceHeaders` as framework context +keys, rejects a contribution that declares any of them, and exposes cancellation only through the +separate `signal` property. A contributor therefore cannot observe or depend on the selected +upstream retry plugin, cache mode, dedupe context replacement, or trace compatibility bridge. +`ServiceClientContext` keeps those fields for existing callers, but transport policy alone +interprets them. + ### Internal adapter ports The implementation MUST introduce exactly three NetScript-owned internal adapter responsibilities. -The following structural contract is normative inside `@netscript/sdk`, but the names are not public -exports and MUST NOT appear in `deno doc` or generated JSR declarations: +They live under `packages/sdk/src/internal/client-contributions/`; the initial files are +`adapter-ports.ts`, `prepared-call.ts`, and `stable-v1-adapter.ts`. That directory has no `mod.ts`, +is absent from `packages/sdk/deno.json` exports, and is imported only by relative package-internal +paths. The following structural contract is normative inside `@netscript/sdk`, but the names are not +public exports and MUST NOT appear in any root/client/ports/desktop `deno doc` graph, generated +declaration, or packed-consumer import: ```ts interface SdkClientLogicalCall { @@ -511,15 +537,26 @@ interface ClientTransportPolicyPort { `ProcedureMetadataPort` is the only component allowed to interpret an upstream procedure node. `PreparedOutboundHeadersPort` performs tuple composition and validation exactly once per logical -call. `ClientTransportPolicyPort` owns every attempt, retry, encoding, trace, and dispatch action -and MUST accept already prepared output; it MUST NOT invoke contributors. The supported v1 adapter -and a future v2 adapter may have different private wiring, but both must satisfy these same port -semantics. - -The prepared call retains one context/snapshot identity and one canonical lower-case header record. -An adapter creates a fresh transport header container for each attempt, but the contributor-owned -entries and the preparation-context projection are byte-equivalent across attempts. Trace fields or -other transport-owned fields are added only after this invariant is established. +call epoch. `ClientTransportPolicyPort` owns every attempt, retry, encoding, trace, and dispatch +action and MUST accept already prepared output; it MUST NOT invoke contributors. The supported v1 +adapter and a future v2 adapter may have different private wiring, but both must satisfy these same +port semantics. + +The normative channel is the direct `PreparedSdkClientCall` argument passed from the preparation +port to the transport port. A stable-v1 realization that must cross an upstream callback MAY also +store that same object under a package-private `unique symbol` declared in `stable-v1-adapter.ts`. +The symbol and value are transport context, never contribution-visible context. An upstream callback +may read only that prepared value; it cannot invoke contributors. If an upstream plugin replaces its +downstream context, the adapter must explicitly preserve or reattach the private value, or use a +per-call closure instead. This is why outer wrapper versus memoized realization remains an +implementation choice but the channel and observable semantics do not. + +The prepared call retains one contribution-context projection identity and one canonical lower-case +header record. An adapter creates a fresh transport header container for each attempt, but the +contributor-owned entries and projection are byte-equivalent across attempts in one logical call +epoch. Transport-only signal, cache, retry, and trace context may be replaced or advanced by the +adapter and are outside this equality assertion. Trace fields or other transport-owned fields are +added only after the contributor-header invariant is established. `defineSdkClientContribution()(descriptor)` preserves `id`, the context declaration, header keys, and cache mode as literals. Its parameter applies these static checks: @@ -587,15 +624,39 @@ conflict validation only at runtime. The client surface becomes context-generic with compatibility defaults: ```ts -export type ServiceRequestRest = RequiredKeys extends never - ? [options?: { readonly context?: TContext }] - : [options: { readonly context: TContext }]; +export interface ServiceRequestOptions< + TContext extends object = ServiceClientContext, +> { + readonly context?: TContext; +} -export type ServiceClientMethod = ( +export type ServiceRequestRest = + RequiredKeys extends never ? [options?: ServiceRequestOptions] + : [options: { readonly context: TContext }]; + +export type ServiceClientMethod< + TInput, + TOutput, + TContext extends object = ServiceClientContext, +> = ( input: TInput, ...request: ServiceRequestRest ) => Promise; +export type ServiceClientShape< + TContract extends ContractLike, + TContext extends object = ServiceClientContext, +> = TContract extends ContractProcedureLike ? ServiceClientMethod< + ProcedureInputFromNode, + ProcedureOutputFromNode, + TContext + > + : { + [K in keyof TContract]: TContract[K] extends ContractLike + ? ServiceClient + : never; + }; + export type ServiceClient< TContract extends ContractLike, TContext extends object = ServiceClientContext, @@ -618,6 +679,30 @@ export interface CreateServiceClientOptions< `ServiceClient>`. All existing single-generic references continue to mean the current `ServiceClientContext`. +Compatibility defaults are normative on every widened public generic. New parameters are appended +after existing parameters so positional type arguments keep their meaning: + +| Surface | Required default | +| ------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- | +| `ServiceRequestOptions` / `ServiceRequestRest` | `ServiceClientContext` | +| `ServiceClientMethod` | `ServiceClientContext` | +| `ServiceClientShape` / `ServiceClient` | `ServiceClientContext` | +| `CreateServiceClientOptions` | `readonly []` for `TContributions` | +| `ActionQueryKey` / `createActionQueryKey<..., TKeySuffix>()` | `readonly []` for `TKeySuffix` | +| `ActionMethod` | `ServiceClientContext`, then `readonly []` | +| `QueryFactory` / `FactoryConfig<...>` | `ServiceClientContext`, then `readonly []` | +| `ServiceQueryClientContext` | `Record` | +| `ServiceQueryKeyOptions` | `Record` | +| `ServiceProcedureQueryOptions` | `Record` | +| `ServiceProcedureInfiniteOptions` | existing `unknown` for `TPageParam`, then `Record` | +| `ServiceProcedureMutationOptions` | existing `unknown` for `TMutationContext`, then `Record` | +| `ServiceProcedureStreamedOptions` / `ServiceProcedureQueryUtils` | `Record` | +| `ServiceQueryUtils` / `createServiceQueryUtils()` | `Record` | +| `DefineServiceConfig` | `readonly []` for `TContributions` | + +The implementation type fixture MUST compile all pre-RFC single-generic/two-generic uses unchanged; +an omitted tuple cannot require a newly written type argument. + ### Query and generated type propagation `DefineServiceConfig` gains the contribution tuple generic. Its mapped results infer one composite @@ -663,15 +748,96 @@ client context itself a safe cache partition. This narrow cache-effect declaration is not a query contribution. It cannot set stale times, retry, invalidation callbacks, query functions, or arbitrary key fragments. +#### Server key algebra and compatibility + +The server cache cannot append the nested TanStack suffix directly: `QueryKeyPart` is primitive and +`CacheKey` is `Deno.KvKey`. RFC-A therefore uses a two-string server suffix. The first string is a +stable tag; the second is `JSON.stringify` over the contribution-id-sorted array of validated +`[id, partition]` pairs. The values are visible, length-bounded, and non-secret by the partition +law. No partitioned contribution means no suffix at all. + +```ts +export type SdkClientServerKeySuffix = + | readonly [] + | readonly ['$netscript.sdk-context', string]; + +export type ActionQueryKey< + TAction extends string = string, + TSuffix extends SdkClientServerKeySuffix = readonly [], +> = readonly [ + resource: string, + action: TAction, + serializedInput: string, + ...suffix: TSuffix, +]; + +export function createActionQueryKey< + const TAction extends string, + const TSuffix extends SdkClientServerKeySuffix = readonly [], +>( + resource: string, + action: TAction, + input: unknown, + suffix?: TSuffix, +): ActionQueryKey; +``` + +Thus a contribution-free or invariant-only service retains the exact public three-tuple. A +partitioned `orders.list` call has the full server key: + +```ts +[ + 'orders', + 'list', + '{"page":1}', + '$netscript.sdk-context', + '[["@netscript/plugin-auth:bearer","principal-7"],["app:locale","de-CH"]]', +]; +``` + +`ActionMethod` and `QueryFactory` append `TContext = ServiceClientContext` and +`TKeySuffix = readonly []` generics. `ActionMethod.key`, its callable operation, `prefetch`, +`getCachedData`, and `getCachedEntry` accept the same conditional context rest used to compute the +partition. Resource/action invalidation methods remain prefix-only and accept no partition. The six +existing server/client bridge surfaces have these normative dispositions: + +| Current surface | RFC-A disposition | +| ----------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `createActionQueryKey(): readonly [string, string, string]` | Return `ActionQueryKey`; the default stays the exact current three-tuple. | +| `ActionMethod.key` and `QueryFactory` | Append defaulted context/suffix generics; full-key and cache-access calls compute one suffix from their request context. | +| `CacheKey = Deno.KvKey` and `CacheQuery` | No public widening. Both suffix elements are strings; storage remains `['cache_query', ...ActionQueryKey]`. | +| `query-client/key-bridge.ts` | No public change. `toClientKeyPrefix` and `bridgeInvalidation` keep resource/action prefixes and never include a partition suffix. | +| `query-client/kv-cache-persister.ts` | No public change. Its opaque serialized TanStack key already contains the generated full-key suffix; two partitions must persist under different storage strings. | +| `collections/create-query-collection.ts` | The low-level manual `queryKey`/`queryFn` pair remains caller-owned. Generated/scaffolded contribution-aware collections MUST take both from the same generated query-options result; a golden/conformance fixture proves an unsuffixed key is never generated beside a partitioned function. | + +TanStack key injection is not a zero-cost type cast. For a context-bearing service, +`createServiceQueryUtils` MUST recursively wrap the upstream utility tree. At each procedure and +nesting level it precomputes the contribution partition for each full-key operation kind (`query`, +`streamed`, `live`, and `infinite`), merges the canonical suffix into the upstream +`optionsIn.queryKey`, and forwards the same context to the query function. Mutation helpers forward +context but do not add a response-cache partition. Partial `.key()`/invalidation prefixes remain +unchanged. The current `return utils as ServiceQueryUtils` fast path is permitted only +for the default empty-context/no-partition specialization. + +The checked-in `service-query-utils-upstream_type.ts` assertion remains valid for +`ServiceQueryUtils` because its new context generic defaults to `Record`. +It MUST NOT be generalized to a contributed specialization: that surface is produced by the wrapper +above and is tested separately. The RFC proof fixture +`packages/sdk/tests/type-fixtures/sdk-client-contributions-rfc_type.ts` pins the default +assignability, real `ContractLike` recursion, contribution-aware `defineServices` result, server key +suffix, and direct-only omission. + ### Composition and ordering law Construction performs these steps in tuple order: 1. validate the protocol family and major, id grammar, tuple/key limits, and plain-object shape; -2. canonicalize declared header names to lower case and reject non-canonical input; -3. reserve framework and Fetch-owned headers; -4. reject duplicate ids, context keys, and header keys; and -5. validate query compatibility and generated surface selection. +2. reject contribution ownership of SDK context keys (`signal`, `cache`, retry fields, and + `traceHeaders`); +3. canonicalize declared header names to lower case and reject non-canonical input; +4. reserve framework and Fetch-owned headers; +5. reject duplicate ids, context keys, and header keys; and +6. validate query compatibility and generated surface selection. At call time: @@ -721,32 +887,57 @@ trace fields after contribution validation. ### Async context, retries, and cancellation -Preparation runs exactly once per logical client call, semantically above the adapter's retry loop. -Retries reuse the same immutable `PreparedSdkClientCall`. This avoids fetching a different -credential or locale halfway through one retry sequence. Credential refresh after a `401` requires a -future explicit replay policy; an interceptor hidden in an auth contribution would make side-effect -replay unsafe. +Preparation runs exactly once per logical call epoch, semantically above the adapter's retry loop. +Unary retries reuse the same immutable `PreparedSdkClientCall`. This avoids fetching a different +credential or locale halfway through one attempt sequence. Credential refresh after a `401` requires +a future explicit replay policy; an interceptor hidden in an auth contribution would make +side-effect replay unsafe. The adapter MUST realize prepare-once with either an outer logical-call wrapper (preferred because -the lifecycle is explicit) or an immutable per-logical-call memo shared by every attempt. Wiring +the lifecycle is explicit) or an immutable per-epoch memo shared by every attempt. Wiring `prepare()` directly to an upstream link-header callback is non-conforming unless that callback -reads only such a memo. Official oRPC `v2.0.0-beta.25` source resolves link headers during input -encoding, while its retry plugin invokes the downstream chain again per attempt; a direct async -header callback therefore runs once per retry, not once per logical call. The supported v1 adapter -must be tested rather than assumed to differ. +reads only such a memo. This behavior is verified, not hypothetical, on the repository's locked oRPC +v1.14.6 family: `StandardRPCLinkCodec.encode()` resolves `headers` for every downstream entry, and +`ClientRetryPlugin` re-enters that downstream chain for every retry. The v2 beta.25 source has the +same relevant lifecycle. Direct async preparation in either link-header callback therefore runs per +attempt and is non-conforming. -A mandatory conformance fixture forces at least one retry and proves all of the following: +A mandatory unary conformance fixture explicitly passes `context.retry: 1` because the current +stable-v1 adapter configures retry off by default (`default.retry = 0`). It proves all of the +following: - contributor preparation count is exactly `1`; - each attempt receives a freshly materialized transport header container; - the canonical contributor-header bytes are identical on every attempt; and -- the logical-call context/procedure projection observed by the adapter is the same immutable +- the contribution context/procedure projection observed by the adapter is the same immutable snapshot on every attempt. +Streaming has a different boundary. Returning an `AsyncIterator` creates a stream session, not an +eternally prepared epoch. A failure raised by `iterator.next()` after the iterator was returned +starts a new reconnect epoch. Before dispatching that reconnect, the SDK MUST rerun contribution +preparation exactly once against the same borrowed input and current contribution context source. +All transport attempts inside the reconnect epoch reuse that new prepared call. The stable-v1 +adapter MUST NOT let `ClientRetryPlugin` perform iterator-phase recovery against the old memo +without this outer re-preparation step. Its existing retry budget and abort signal still bound +whether another epoch is attempted; retry remains transport policy and is not contributor-visible. + +The iterator-phase conformance fixture explicitly enables retry, opens a credential-bearing stream +with credential `A`, consumes one item, rotates the source to `B`, forces `iterator.next()` to fail, +and observes the reconnect. Required assertions are: preparation count `2` (one per epoch), initial +attempts contain `A`, reconnect attempts contain `B`, and every attempt within each epoch is +byte-equivalent. An aborted stream starts no new epoch. This rule prevents a long-lived stream from +reconnecting indefinitely with a frozen bearer while preserving prepare-once for ordinary retries. + +The stable-v1 dedupe path is header-safe: its request identity includes body, headers, method, and +URL. Because prepared contributor headers exist before dedupe, calls with different bearer or locale +values do not coalesce. Dedupe may replace downstream transport context with a group context; that +does not alter the already prepared header record and is why conformance compares the contribution +projection rather than the whole `ServiceClientContext` object. + If the call signal is already aborted, no contributor runs. If it aborts during an async resolver, the SDK stops awaiting, does not dispatch, and rejects with the platform abort reason. A resolver -receives the signal through `ServiceClientContext` and SHOULD stop its own work. The SDK cannot -cancel arbitrary promise side effects. +receives the signal through `SdkClientPrepareOptions.signal` and SHOULD stop its own work. The SDK +cannot cancel arbitrary promise side effects. The snapshot is shallowly read-only at the type level and its top-level records are frozen in development/test builds. The SDK does not deep-clone input or context, because that would destroy @@ -758,8 +949,8 @@ must not mutate them. Version 1 contributes only prepared outbound header values and typed per-call context. It does not contribute an upstream callback. The initial stable-v1 adapter may map an already prepared record into the native link-header facility, provided that preparation occurs above retries or through the -specified per-call memo. A future v2 adapter may use different private wiring. These are -non-normative adapter choices; the three NetScript ports and prepare-once behavior are normative. +specified per-epoch memo. A future v2 adapter may use different private wiring. These are +non-normative adapter choices; the three NetScript ports and once-per-epoch behavior are normative. The SDK remains the sole owner of: @@ -789,6 +980,23 @@ reserves `traceparent` and `tracestate`. The W3C [Trace Context recommendation](https://www.w3.org/TR/trace-context/) also requires careful mutation and calls out correlation/privacy risk. +#### Desktop transport boundary + +RFC-A version 1 is an HTTP request-header axis. `@netscript/sdk/desktop` uses an oRPC MessagePort +link and has no HTTP request or header channel, so it is explicitly out of scope rather than +silently supported. `CreateDesktopServiceClientOptions` does not gain `contributions`. Its +TypeScript excess-property check and runtime construction validation MUST reject a supplied +`contributions` field with `SDK_CONTRIBUTION_TRANSPORT_UNSUPPORTED`; JavaScript/widened input must +not be accepted and ignored. `SdkClientContributionReference.targets` remains only `browser` and +`server`, and generators fail if an HTTP contribution is selected for a desktop target. + +Consequently, creating a desktop client from the same contract does not send bearer or locale +headers over MessagePort. Auth-core and desktop docs MUST state this. If a desktop native host later +calls an HTTP service, the host creates a separate HTTP `createServiceClient()` and supplies its own +contribution context; the webview credential is never ambiently forwarded across the native bridge. +A future MessagePort contribution/capability seam requires a separate RFC and cannot reuse +`headerKeys` as if MessagePort had headers. + #### Optional incoming server companion oRPC v2's [`RequestHeadersHandlerPlugin`](https://v2.orpc.dev/docs/plugins/request-headers) is an @@ -805,11 +1013,21 @@ RFC-A client metadata enforce server authorization. #### Boundaries reserved for the v2 migration -RFC-A does not adopt v2's typed-error/status-map redesign or its `@orpc/opentelemetry` integration. -It also does not change HTTP method selection: transport owns GET/POST, and any later v2 adapter -that enables GET must prove an explicit CSRF law. NetScript continues to own its client-span -topology and final trace injection unless the separate v2 RFC proves that upstream instrumentation -can replace them without missing spans or emitting duplicates. +RFC-A does not adopt v2's typed-error/status-map redesign. Stable v1 already enables GET inference +today through `inferRPCMethodFromContractRouter`, and the SDK's dedupe filter is GET-only. The +separate v2 migration must choose explicitly between: + +1. preserve GET by reimplementing the removed method-inference behavior, enabling GET in the v2 + server's `allowMethods`, and defining a `Sec-Fetch-Mode`/CSRF law; or +2. adopt v2's POST-oriented default, explicitly retire current GET behavior, and replace or remove + the now-ineffective GET-only dedupe policy. + +Silently accepting POST-only behavior while leaving the current dedupe filter installed is not a +valid migration. The `@orpc/opentelemetry` package name is also not exclusively a v2 concern: that +package ships on the maintained v1 line. Selecting/renaming the v1 instrumentation dependency +belongs to transport issue #1351. The v2 spike owns only proof of span topology, execution counts, +and absence of double spans before any change to NetScript's final trace injection. RFC-A continues +to own neither typed-error/status migration nor telemetry-package migration. ### Error and failure model @@ -825,6 +1043,7 @@ export type SdkClientContributionErrorCode = | 'SDK_CONTEXT_MISSING' | 'SDK_HEADER_INVALID' | 'SDK_CACHE_PARTITION_INVALID' + | 'SDK_CONTRIBUTION_TRANSPORT_UNSUPPORTED' | 'SDK_PREPARATION_FAILED'; export interface SdkClientContributionDiagnostic { @@ -859,6 +1078,7 @@ that need internal diagnostics must observe and sanitize their own source failur | Resolver rejects or throws | preparation | Throw stable `SDK_PREPARATION_FAILED`; discard the source error from the public failure. | | Undeclared, forbidden, non-string, or CR/LF header | preparation | Throw `SDK_HEADER_INVALID`; do not dispatch. | | Invalid partition syntax | partition | Throw before cache access. First-party tests separately reject known secret sources; arbitrary secrets cannot be detected reliably at runtime. | +| Contribution supplied to Desktop/unsupported link | compile when literal; construction always | Reject rather than ignoring it; name the unsupported transport without including context or header values. | | Abort before/during preparation | preparation | Propagate abort reason; do not dispatch. | | Discovery, codec, network, retry, or server-defined error | transport | Preserve the existing SDK/oRPC error path; do not relabel it as a contribution failure. | @@ -881,6 +1101,12 @@ name, service name, and duration. Debug mode does not relax this list. The [OWASP logging guidance](https://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html#data-to-exclude) specifically excludes access tokens and session identifiers from direct logs. +`prepare` receives raw `input: unknown`, including values owned by application or third-party +schemas. It is sensitive borrowed data: a contribution may inspect it only to decide its declared +headers and MUST NOT log, persist, retain, hash for telemetry, copy it into an error, return it from +the patch, or use it as a cache partition. Installing a third-party contribution grants this +per-call visibility and must be documented as part of plugin trust review. + Partition values are intentionally visible in query keys and developer tools. The API docs and runtime diagnostics MUST say this. First-party auth accepts only an explicitly supplied non-secret partition and never derives one from a bearer token. @@ -971,10 +1197,14 @@ Version 1 sets explicit budgets: The limit applies per service, so a large `defineServices` map does not create one repository-wide intersection. The implementation uses tail recursion over literal tuples and named conflict markers. -A scratch Deno type probe on the RFC branch checked two composed contexts, required call arguments, -a duplicate-context diagnostic, an accepted 16-element tuple, and a rejected 17-element tuple in -0.67 seconds with a 225,508 KiB maximum RSS on the authoring host. That timing is evidence, not a -portable CI threshold. +The committed compile-only fixture +[`packages/sdk/tests/type-fixtures/sdk-client-contributions-rfc_type.ts`](../packages/sdk/tests/type-fixtures/sdk-client-contributions-rfc_type.ts) +models the proposed algebra against the real `ContractLike`, `DefineServiceConfig`/`defineServices` +result shape, `ServiceClient`, `ServiceQueryUtils`, and server key primitives. It checks two +composed contexts, default generic assignability, required call/query arguments, direct-only +omission, a duplicate-context diagnostic, an accepted 16-element tuple, and a rejected 17-element +tuple. The fixture's measured time/RSS is recorded in the harness worklog and remains informational +rather than a portable CI threshold. Raising a budget without changing semantics is a backward-compatible implementation decision after type-performance evidence. Removing a limit or accepting a previously invalid descriptor does not @@ -1003,32 +1233,53 @@ Generated projects change only when the user selects a contributor. Because this RFC changes public and publish surfaces, implementation packages must bump versions according to the release plan and pass JSR isolated-declaration gates. No implementation is allowed -to publish an `@orpc/*` type in a generated `.d.ts`/JSR declaration. More strongly, the public SDK -protocol and all generated public declarations MUST contain zero raw oRPC symbols: no upstream -module specifier, link, plugin, context, interceptor, metadata accessor, or structural alias whose -meaning depends on an upstream major. NetScript-owned public types may be implemented by an +to add an `@orpc/*` identity to an RFC-A declaration. The zero-oRPC gate is deliberately scoped to +(a) every new RFC-A protocol/descriptor/context/cache/error/reference/auth declaration and (b) +generated client declarations. Those targets MUST contain zero raw upstream module specifiers, +links, plugins, contexts, interceptors, metadata accessors, or structural aliases whose meaning +depends on an upstream major. NetScript-owned public types may be implemented by an upstream-specific private adapter but cannot inherit its identity. +For public modules, the declaration gate filters `deno doc --json` to the named RFC-A symbols and +scans those nodes; it does not scan the entire unchanged `@netscript/sdk/ports` graph. Generated +client files are scanned in full because they have no historical compatibility surface. + +The gate does not claim the unchanged SDK/contracts surface is already clean. Current +`ContractProcedureLike`/`ContractLike` expose the literal `~orpc` structural accessor, and the +doctrine sanctions real oRPC builder types in `@netscript/contracts`. Those exact pre-existing paths +are an allowlist tied to type-soundness umbrella #1278 and repair issue #1350; the allowlist may not +grow and does not exempt a new RFC-A symbol. #1350 may reduce the leak while repairing the base +error map, but RFC-A does not make its unrelated zero-oRPC scan a prerequisite for the minimal +client seam. + The first implementation's compatibility target is the supported stable-v1 adapter. A later v2 spike must run the same contribution conformance suite against its adapter before any migration RFC can propose production adoption. Passing RFC-A on stable v1 does not imply v2 compatibility, and adding a v2 adapter must not change the contribution protocol major. +Workspace manifests currently use compatible `^1.14.x` ranges; `deno.lock` is the only exact family +pin. The separate v1.15.0 decision uses lock-only pinning: keep compatible manifest ranges, update +the entire oRPC family atomically in the lock, and require `deno ci --frozen` plus dependency-graph +evidence that no mixed v1 family version resolves. Exact manifest pins are not introduced by RFC-A. +The fact that v1.15.0 shipped after the then-current v2 beta confirms stable v1 remains maintained; +staying on v1 for RFC-A is not a migration to an abandoned line. + ### Staged implementation plan and issue decomposition Implementation remains outside this RFC PR. -| Stage | Existing owner | Scope and exit condition | -| ------------------------------ | ----------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| 0. Ratify | [#1348](https://github.com/rickylabs/netscript/issues/1348) | Accept this RFC, settle safe FCP questions, and reconcile child issue bodies. | -| 1. Contract/type repair | [#1350](https://github.com/rickylabs/netscript/issues/1350) | Preserve the concrete base error map and initialize/export `NetScriptProcedureMeta`; type fixtures prove both. | -| 2. Minimal client seam | [#1349](https://github.com/rickylabs/netscript/issues/1349) | Add descriptor/helper, tuple algebra, context-generic client/query surfaces, the three internal ports, prepare-once stable-v1 composition, cache-effect handling, and failures. Do not expose upstream callback arrays. | -| 3. Transport consolidation | [#1351](https://github.com/rickylabs/netscript/issues/1351) | Decide separately whether to move the exact oRPC v1 family to stable v1.15.0, keep one fetch/retry/dedupe/trace path, prove prepare-once across retry, and deprecate current no-op options. No v2 migration. | -| 4. Auth dogfood | [#1352](https://github.com/rickylabs/netscript/issues/1352) | Ship the auth-core bearer factory, access metadata behavior, redaction, cache partition/direct-only modes, manifest reference, docs, and scaffold choice. | -| 5. Trace ownership proof | [#1353](https://github.com/rickylabs/netscript/issues/1353) | Re-scope from “trace contribution” to prove the transport retains the only final trace injection and rejects contributor ownership of trace headers. | -| 6. Non-auth proof | new child after RFC acceptance | Ship/test locale contribution, partitioned keys, header conflicts, and generated use. Do not file during this RFC run. | -| 7. Generic discovery | [#1093](https://github.com/rickylabs/netscript/issues/1093) | Discover third-party module references without hardcoded factories; generated selection remains explicit. | -| 8. oRPC v2 migration RFC/spike | new owner after RFC-A review; do not file in this run | Wait for stable unless the owner explicitly accepts beta; prove a complete, coordinated adapter migration independently of RFC-A. | +| Stage | Existing owner | Scope and exit condition | +| ------------------------------ | ----------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| 0. Ratify and reconcile board | [#1348](https://github.com/rickylabs/netscript/issues/1348) | Accept this RFC, settle safe FCP questions, then align #1349–#1353 bodies before implementation. In particular, decide whether #1350 is explicitly widened to metadata or a dependent metadata child is filed; its current `safe()` title/body do not silently own metadata. | +| 1a. Existing error repair | [#1350](https://github.com/rickylabs/netscript/issues/1350) | Preserve the concrete base error map and client error channel exactly as filed. This remains a type-soundness #1278 child. | +| 1b. Procedure metadata | owner selected in Stage 0; do not file in this run | Initialize/export `NetScriptProcedureMeta` without re-erasing Stage 1a types. Either an amended #1350 or an explicit dependent child owns this before auth dogfood. | +| 2. Minimal client seam | [#1349](https://github.com/rickylabs/netscript/issues/1349) | Add descriptor/helper, tuple algebra, defaulted context-generic client/query surfaces, private `src/internal/client-contributions/` ports, server/TanStack key algebra, stable-v1 composition, reconnect preparation, desktop rejection, cache handling, and failures. No upstream callback arrays. | +| 3. Transport consolidation | [#1351](https://github.com/rickylabs/netscript/issues/1351) | Decide separately whether to move the lock-pinned whole oRPC v1 family to stable v1.15.0, keep one fetch/retry/dedupe/trace path, prove unary/reconnect semantics and header-safe dedupe, and deprecate current no-op options. Selecting/renaming v1 OTel belongs here; no v2 migration. | +| 4. Auth dogfood | [#1352](https://github.com/rickylabs/netscript/issues/1352) | Ship the auth-core bearer factory, access metadata behavior, redaction, cache partition/direct-only modes, manifest reference, docs, and scaffold choice. | +| 5. Trace ownership proof | [#1353](https://github.com/rickylabs/netscript/issues/1353) | Re-scope from “trace contribution” to prove the transport retains the only final trace injection and rejects contributor ownership of trace headers. | +| 6. Non-auth proof | new child after RFC acceptance | Ship/test locale contribution, partitioned keys, header conflicts, and generated use. Do not file during this RFC run. | +| 7. Generic discovery | [#1093](https://github.com/rickylabs/netscript/issues/1093) | Discover third-party module references without hardcoded factories; generated selection remains explicit. | +| 8. oRPC v2 migration RFC/spike | new owner after RFC-A review; do not file in this run | Wait for stable unless the owner explicitly accepts beta; prove a complete, coordinated adapter migration independently of RFC-A, including the keep-GET versus retire-GET decision. | Issue #451 remains the sole future owner of custom links. #928 and #934 consume aligned protocol and metadata vocabulary but are not prerequisites for the header seam. The org-aware policy work in @@ -1044,10 +1295,18 @@ The separate v2 RFC/spike must, at minimum, gate all of the following before pro - prove route, metadata, OpenAPI, and Scalar output parity; - prove typed-error semantics and HTTP status-map parity without folding the migration into #1350; - audit middleware execution counts now that v2 removes automatic deduplication; -- define the GET/POST/CSRF law; +- choose and prove a complete GET/POST/CSRF law: either (a) preserve current GET with a NetScript + replacement for removed `inferRPCMethodFromContractRouter`, explicit server `allowMethods`, and + `Sec-Fetch-Mode`/CSRF behavior, or (b) retire GET, document the selected POST/PUT/PATCH/DELETE + methods and CSRF behavior, and update routes/docs; +- prove request dedupe remains effective under the chosen method policy; a GET-only filter that + becomes a silent no-op fails this gate; - prove OpenTelemetry topology and absence of double spans before changing final injection - ownership; -- prove Fresh/desktop serializer parity and SSE/stream lifecycle behavior; + ownership, while keeping any stable-v1 `@orpc/otel` to `@orpc/opentelemetry` package decision in + #1351; +- prove Fresh and Desktop MessagePort serializer parity, including browser/native framing; +- prove SSE/stream opening, iterator-phase reconnect, cursor, cancellation, and credential refresh + lifecycle behavior; - re-run query-key/cache-partition safety because v2 still excludes client context from keys; - pass the Deno/browser/server matrix, package checks, full CLI/scaffold E2E, documentation snippets, and publish dry-run. @@ -1064,10 +1323,16 @@ An implementation is not complete until all applicable gates pass. 17-element tuple have `@ts-expect-error` fixtures; - `defineServices`, server query factories, TanStack query/infinite/mutation options, and `.call` preserve the per-service context; +- every widened public generic compiles under its compatibility default; existing single-generic + `ServiceClient`/`ServiceQueryUtils` and current upstream-assignability fixtures remain valid; +- the server key algebra proves the default exact three-tuple and the partitioned five-tuple, while + `CacheKey` remains `Deno.KvKey` and invalidation prefixes remain unsuffixed; - `direct-only` service keys are absent from query/query-utils mapped types; - server-defined error inference remains exact after metadata initialization; and -- public and generated declarations contain zero raw oRPC module specifiers or symbols, including - links, plugins, contexts, interceptors, and metadata accessors. +- new RFC-A protocol/descriptor/context/cache/error/reference/auth declarations and generated client + declarations contain zero raw oRPC module specifiers or symbols. The scan uses a non-growing + allowlist for current `ContractLike`/contracts declarations tied to #1350/#1278 rather than + scanning those unchanged surfaces as if they were clean. #### Runtime gates @@ -1075,10 +1340,20 @@ An implementation is not complete until all applicable gates pass. - duplicate validation repeated through `unknown`/JavaScript input; - undeclared, mixed-case, forbidden, CR/LF, non-string, and duplicate headers rejected; - base `Content-Type` and final trace fields cannot be overwritten; -- a forced retry records preparation count `1` and byte-equivalent prepared contributor - headers/context on every attempt; +- a forced unary retry explicitly sets `context.retry: 1`, records preparation count `1`, and + observes byte-equivalent prepared contributor headers/projection on every attempt; +- an iterator-phase reconnect rotates credential `A` to `B`, records one preparation per epoch, + never reuses `A` on the reconnect, and starts no epoch after abort; +- contribution callbacks cannot observe SDK retry/cache/trace fields; signal is exposed only by the + separate preparation option; +- stable-v1 dedupe identity includes prepared headers, so distinct auth/locale requests do not + coalesce even when other request fields match; - locale and two auth partitions cannot share cached data, while prefix invalidation still works; +- persisted TanStack keys and generated collection wiring keep partitioned key/function pairs + together; unsuffixed generated goldens fail; - direct-only services have no runtime query/query-utils property; and +- Desktop construction/generation rejects contributions instead of ignoring them, while normal + MessagePort calls remain unchanged; and - every error/log/span snapshot excludes header values, input, context, partitions' source values, source messages, tokens, and session ids. @@ -1086,7 +1361,16 @@ An implementation is not complete until all applicable gates pass. - the supported stable-v1 adapter passes the entire contribution conformance suite; - its upstream link-header callback, if used, consumes only the already prepared per-call record; -- the package declaration graph and generated client declarations pass the zero-oRPC-symbol scan; +- implementation files live only under `src/internal/client-contributions/`, with no internal barrel + or `deno.json` export; +- `deno doc --json` for SDK root, `./client`, `./ports`, and `./desktop`, plus a packed-consumer + negative import fixture, prove `ProcedureMetadataPort`, `PreparedOutboundHeadersPort`, + `ClientTransportPolicyPort`, `PreparedSdkClientCall`, and the private context symbol are absent; +- that packed fixture specifically rejects `@netscript/sdk/internal/client-contributions`, + `@netscript/sdk/internal/client-contributions/adapter-ports`, and + `@netscript/sdk/client-contributions` as unexported module specifiers; +- the scoped new-declaration and generated-client zero-oRPC scan passes with no growth in the + #1350/#1278 allowlist; - a future v2 spike adapter must pass the same suite before its migration RFC can enter FCP; and - v2 typed-error/status-map and OpenTelemetry migration tests remain outside RFC-A. @@ -1096,11 +1380,16 @@ An implementation is not complete until all applicable gates pass. - duplicate/mismatched ids and target-incompatible exports fail `plugin doctor`/generation; - generated code uses public exports, static imports, `as const`, and explicit service selection; - removing auth from generated config removes the context requirement and wire header; and +- selecting an HTTP contribution for `@netscript/sdk/desktop` is a generator/type/runtime error; it + is never silently omitted; and - auth and locale scaffold doctests type-check. #### Repository and publish gates - scoped check/lint/fmt wrappers for changed TypeScript; +- `deno check --unstable-kv packages/sdk/tests/type-fixtures/sdk-client-contributions-rfc_type.ts` + proves the committed real-surface 16/17 inference model until implementation replaces its local + types with public imports; - focused package tests, `deno task arch:check`, and docs/RFC link/lint checks; - `deno doc --lint` for every affected public module; - `deno publish --dry-run --allow-dirty` and the repository JSR audit for `contracts`, `sdk`, @@ -1119,7 +1408,12 @@ Implementation updates must cover: - plugin manifest/config builder documentation; - generated service-client templates and embedded CLI assets; - query partition visibility, direct-only behavior, and cache invalidation; -- upstream-major neutrality, the private adapter boundary, and prepare-once retry behavior; +- exact server/TanStack key suffixes, collection/persister behavior, and default-generic + compatibility; +- upstream-major neutrality, scoped existing `ContractLike` debt, the private adapter location and + absence guarantees, unary prepare-once behavior, and fresh preparation on stream reconnect; +- the HTTP-only contribution boundary for Desktop MessagePort clients and the required rejection + behavior; - the optional incoming request-header companion and direct-call absence behavior; - CORS/preflight, cleartext bearer, cookie, redirect, and retry limitations; and - migration notes for manual header wrappers and deprecated `port`/`timeout` fields. @@ -1241,12 +1535,14 @@ custom-link design gets its own breaking assessment. - oRPC v2's [TanStack integration](https://v2.orpc.dev/docs/integrations/tanstack-query#client-context) explicitly excludes client context from query keys, preserving RFC-A's partition/direct-only law. -- In oRPC `v2.0.0-beta.25`, the +- The locked oRPC v1.14.6 package was executed/inspected in-tree: its standard codec resolves + headers in `encode`, retry re-enters downstream per attempt and from iterator consumption, and + dedupe identity includes headers. The corresponding v2 beta.25 [standard link codec](https://github.com/middleapi/orpc/blob/v2.0.0-beta.25/packages/client/src/adapters/standard/rpc-link-codec.ts) - resolves headers during encoding and the + and [retry plugin](https://github.com/middleapi/orpc/blob/v2.0.0-beta.25/packages/client/src/plugins/retry.ts) - invokes downstream per attempt. This proves that direct link-header preparation is not - prepare-once. + confirm that these lifecycle assumptions cannot be hidden behind an upstream-major-neutral public + callback. - Official [oRPC releases](https://github.com/middleapi/orpc/releases) mark v2 beta releases as pre-release and v1.15.0 as the latest stable release as of the audit date. - The WHATWG [Fetch Standard](https://fetch.spec.whatwg.org/#forbidden-request-header) defines @@ -1258,8 +1554,8 @@ custom-link design gets its own breaking assessment. ## Unresolved questions -These are safe for discussion/FCP because the upstream-neutral extension law, prepare-once -invariant, and separate-v2 boundary remain fixed: +These are safe for discussion/FCP because the upstream-neutral extension law, unary/reconnect +preparation invariant, and separate-v2 boundary remain fixed: 1. Should the first implementation reserve exactly 16 contributions, or raise the ceiling if CI type fixtures demonstrate equal cost? It must not ship below 16. @@ -1271,29 +1567,33 @@ invariant, and separate-v2 boundary remain fixed: 4. Maintainers may refine public names (`responseCache`, `direct-only`, or the access enum) during FCP while preserving the specified semantics and defaults. 5. Should the stable-v1 adapter use an outer logical-call wrapper (the RFC's preference) or - immutable per-logical-call memoization? Either choice must pass preparation-count `1` and - byte-equivalent retry fixtures; direct unmemoized link-header preparation is not allowed. + immutable per-epoch memoization? Either choice must pass preparation-count `1` and + byte-equivalent unary retry fixtures, use the specified direct/private-symbol channel, preserve + it across context replacement, and start a fresh preparation epoch for iterator reconnect. 6. Should the semantic procedure-auth metadata requirement be accepted inside RFC-A and implemented - through #1350, as written, or ratified in a dependent mini-RFC? The public metadata vocabulary - and upstream-neutral metadata port are required before auth dogfood can ship. + by explicitly widening #1350 after acceptance, or ratified in a dependent mini-RFC/child? The + current #1350 remains the `safe()`/error repair until that Stage-0 board decision. The public + metadata vocabulary and upstream-neutral metadata port are required before auth dogfood can ship. 7. Does the owner want the optional stable-v1 incoming request-header handler installed by default in service presets, or explicitly selected? Direct calls must continue to tolerate absent request headers under an explicit server policy. 8. Should the separately reviewed stable-v1.15.0 exact-family upgrade precede the minimal client seam, or should RFC-A first implement against the current v1.14.x family? RFC-A supports either - stable-v1 baseline and does not authorize v2. + stable-v1 baseline, uses the normative lock-only whole-family gate, and does not authorize v2. 9. For the separate v2 migration RFC, must production support zero-downtime mixed-version clients via parallel endpoints, or is a coordinated atomic client/server rollout acceptable? -10. Does Fable agree that GET enablement and its CSRF law belong exclusively to the transport/v2 - migration RFC rather than RFC-A contributions? +10. In the separate v2 migration, should NetScript preserve today's inferred GET behavior by + replacing removed method inference plus configuring `allowMethods`/CSRF, or intentionally retire + GET and replace the GET-only dedupe policy? RFC-A contributions do not choose either path. 11. Can v2 OpenTelemetry instrumentation ever replace NetScript's final trace injection without - violating NetScript span ownership or creating double spans? This is a v2-spike proof - obligation, not an RFC-A implementation choice. + violating NetScript span ownership or creating double spans? Stable-v1 package + selection/renaming remains #1351; only topology replacement is a v2-spike proof obligation. The following are not open: duplicate rejection, order independence, per-call async preparation, -exactly-once preparation per logical call, reserved trace ownership, zero upstream types/symbols in -public and generated declarations, no upstream callback arrays, explicit plugin selection, cache -partition/direct-only safety, separation from contract-defined errors, and no production v2 beta +once-per-epoch preparation plus fresh stream reconnect credentials, reserved trace ownership, zero +upstream identities in new RFC-A/generated client declarations (under the scoped #1350/#1278 +baseline), no upstream callback arrays, explicit plugin selection, cache partition/direct-only +safety, Desktop rejection, separation from contract-defined errors, and no production v2 beta migration in RFC-A. ## Future possibilities From bc955459046c19a31fe00195b32f37f25a04e24f Mon Sep 17 00:00:00 2001 From: Rickylabs Date: Sat, 8 Aug 2026 20:54:10 +0200 Subject: [PATCH 08/12] docs(harness): record sdk RFC plan remediation handoff --- .../docs-rfc-sdk-client-contribution--rfc/context-pack.md | 5 +++-- .../docs-rfc-sdk-client-contribution--rfc/final-handoff.md | 4 ++-- .llm/runs/docs-rfc-sdk-client-contribution--rfc/worklog.md | 1 + 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/context-pack.md b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/context-pack.md index ffa5084093..5d57f5feea 100644 --- a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/context-pack.md +++ b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/context-pack.md @@ -154,5 +154,6 @@ milestones. Findings should cite RFC headings and classify blocking versus safe - Handoff baseline: `e78ac0a65f5475ed37152272b16ba7d89deca8c3`. - Audit amendment: `7a0d398087a6608ff1a55bb9fe4c47158edb72a7`. - Formal evaluator artifact: `f1a29fe1a65d59f71a59bf4b6b2a48fc49e1e86f`. -- Cycle-1 remediation and final handoff commits are recorded here after creation; the PR comment - records the final pushed HEAD because an artifact cannot contain its own commit id. +- Cycle-1 remediation: `78a7cecd1d5eaafa7a65bc25a21af497567128dc`. +- The final handoff commit is recorded here after creation; the PR comment records the final pushed + HEAD because an artifact cannot contain its own commit id. diff --git a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/final-handoff.md b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/final-handoff.md index b6b909b562..26ca1f8e94 100644 --- a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/final-handoff.md +++ b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/final-handoff.md @@ -8,7 +8,7 @@ | Branch | `docs/rfc-sdk-client-contribution` | | Base | `origin/main` at `fac9e339042c5394bf882311657d8981d353a1c3` | | Formal cycle-1 verdict | `FAIL_PLAN / CHANGES_REQUESTED`; `plan-eval.md` at `f1a29fe1a65d59f71a59bf4b6b2a48fc49e1e86f` | -| Reviewable remediation commit | `REMEDIATION_COMMIT_PENDING` | +| Reviewable remediation commit | `78a7cecd1d5eaafa7a65bc25a21af497567128dc` | | RFC | `rfcs/0000-sdk-client-contributions.md` (`0000`, Draft) | | Run dir | `.llm/runs/docs-rfc-sdk-client-contribution--rfc/` | | Requested lifecycle | exactly one `status:plan-eval` after push | @@ -62,7 +62,7 @@ implementation, and upstream-major-neutral public/generated RFC-A declarations. | Repository docs links/accuracy | PASS — 102 documents/0 broken; accuracy PASS | | Doctrine | PASS — `deno task arch:check` exit 0; warning-only baseline unchanged | | Diff hygiene | PASS — `git diff --check` | -| Review threads | `VALIDATION_PENDING` | +| Review threads | PASS — 0 total / 0 unanswered | | Git/PR metadata | `VALIDATION_PENDING` | No CLI/scaffold runtime E2E is appropriate for this RFC-only change; implementation stages retain diff --git a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/worklog.md b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/worklog.md index 33175b8e7c..0905da2b43 100644 --- a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/worklog.md +++ b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/worklog.md @@ -192,6 +192,7 @@ considered complete. | 2026-08-08 | 5 | type fixture | Added the in-tree compile-only real-surface fixture covering current defaults, contract recursion, contribution-aware results, exact 3/5 server keys, conflicts, and 16/17 limits. | | 2026-08-08 | 5 | design remediation | Scoped the zero-upstream gate; completed key/default/reconnect/Desktop/private-port/context laws; corrected v2 GET/OTel/lock gates; reconciled #1350 Stage 1a versus metadata Stage 1b. | | 2026-08-08 | 5 | focused validation | Targeted Markdown/TypeScript format, fixture lint/check, focused and 102-document links, docs accuracy, doctrine, and diff hygiene all exit 0; warning-only doctrine/dependency baseline is unchanged. | +| 2026-08-08 | 5 | remediation commit | Committed the RFC, in-tree type fixture, and author-owned harness correction as `78a7cecd1d5eaafa7a65bc25a21af497567128dc`. | ## Decisions From 4978f7d844f05dae9c3236cd830a2b3c5b693dda Mon Sep 17 00:00:00 2001 From: Rickylabs Date: Sat, 8 Aug 2026 20:56:19 +0200 Subject: [PATCH 09/12] docs(harness): finalize RFC-A cycle-two reviewer handoff --- .../context-pack.md | 53 ++++++++++--------- .../final-handoff.md | 23 ++++---- .../supervisor.md | 6 ++- .../worklog.md | 9 +++- 4 files changed, 50 insertions(+), 41 deletions(-) diff --git a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/context-pack.md b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/context-pack.md index 5d57f5feea..61bcea47ad 100644 --- a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/context-pack.md +++ b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/context-pack.md @@ -2,14 +2,14 @@ ## Run Metadata -| Field | Value | -| -------------- | ----------------------------------------------------------------------- | -| Run ID | `docs-rfc-sdk-client-contribution--rfc` | -| Branch | `docs/rfc-sdk-client-contribution` | -| Current phase | `plan-eval`; cycle-1 remediation ready for owner-directed Fable cycle 2 | -| Archetype | `2 + 4 + 5 + 6` described; docs-only PR | -| Scope overlays | `SCOPE-docs` | -| PR | `https://github.com/rickylabs/netscript/pull/1390` | +| Field | Value | +| -------------- | ------------------------------------------------------------------------ | +| Run ID | `docs-rfc-sdk-client-contribution--rfc` | +| Branch | `docs/rfc-sdk-client-contribution` | +| Current phase | `plan-eval`; cycle-1 remediation pushed for owner-directed Fable cycle 2 | +| Archetype | `2 + 4 + 5 + 6` described; docs-only PR | +| Scope overlays | `SCOPE-docs` | +| PR | `https://github.com/rickylabs/netscript/pull/1390` | ## Current State @@ -82,22 +82,22 @@ addition is a compile-only RFC type fixture. ## Gate Snapshot -| Gate | Status | Evidence | -| ------------------------------- | ------------------ | ------------------------------------------------------------------------------- | -| RFC formatting | pass | `deno fmt --check` | -| RFC internal links | pass | focused repo link checker, 0 broken | -| Repository docs links/accuracy | pass | both tasks exit 0 | -| Type fixture | pass | In-tree Deno check; real defaults/key shapes plus 16 accepted/17 rejected | -| Package dry-run baseline | pass | contracts/sdk/plugin/auth-core all report dry-run OK | -| JSR package audit | baseline finding | plugin audit exit 1 on pre-existing module tags/cardinality; other three exit 0 | -| Doc-lint baseline | baseline finding | combined private refs 9/3/15/4 respectively; RFC adds none | -| Doctrine | pass | `deno task arch:check` exits 0; existing warnings are baseline | -| PLAN-EVAL cycle 1 | fail/remediated | Fable F-A1–F-A10 accepted; cycle-2 PASS remains external | -| Audit amendment evidence | pass | 59-line input hashed; 91/74 file scan; seven v1 dependencies behind to 1.15.0 | -| Audit amendment gates | pass | format, links, accuracy, type proof, doctrine, and diff hygiene | -| Pre-amendment PR reconciliation | pass | draft, required labels, sole `status:plan-eval`, no milestone/closing keyword | -| Cycle-1 remediation gates | pass | format/lint/type, RFC/repo links, accuracy, doctrine, and diff hygiene exit 0 | -| Cycle-2 PR reconciliation | pending final step | final pushed HEAD and sole `status:plan-eval` will be recorded in phase comment | +| Gate | Status | Evidence | +| ------------------------------- | ---------------- | ----------------------------------------------------------------------------------- | +| RFC formatting | pass | `deno fmt --check` | +| RFC internal links | pass | focused repo link checker, 0 broken | +| Repository docs links/accuracy | pass | both tasks exit 0 | +| Type fixture | pass | In-tree Deno check; real defaults/key shapes plus 16 accepted/17 rejected | +| Package dry-run baseline | pass | contracts/sdk/plugin/auth-core all report dry-run OK | +| JSR package audit | baseline finding | plugin audit exit 1 on pre-existing module tags/cardinality; other three exit 0 | +| Doc-lint baseline | baseline finding | combined private refs 9/3/15/4 respectively; RFC adds none | +| Doctrine | pass | `deno task arch:check` exits 0; existing warnings are baseline | +| PLAN-EVAL cycle 1 | fail/remediated | Fable F-A1–F-A10 accepted; cycle-2 PASS remains external | +| Audit amendment evidence | pass | 59-line input hashed; 91/74 file scan; seven v1 dependencies behind to 1.15.0 | +| Audit amendment gates | pass | format, links, accuracy, type proof, doctrine, and diff hygiene | +| Pre-amendment PR reconciliation | pass | draft, required labels, sole `status:plan-eval`, no milestone/closing keyword | +| Cycle-1 remediation gates | pass | format/lint/type, RFC/repo links, accuracy, doctrine, and diff hygiene exit 0 | +| Cycle-2 PR reconciliation | pass | draft/main, required labels, sole `status:plan-eval`, milestone null, explicit push | ## JSR Consequences @@ -155,5 +155,6 @@ milestones. Findings should cite RFC headings and classify blocking versus safe - Audit amendment: `7a0d398087a6608ff1a55bb9fe4c47158edb72a7`. - Formal evaluator artifact: `f1a29fe1a65d59f71a59bf4b6b2a48fc49e1e86f`. - Cycle-1 remediation: `78a7cecd1d5eaafa7a65bc25a21af497567128dc`. -- The final handoff commit is recorded here after creation; the PR comment records the final pushed - HEAD because an artifact cannot contain its own commit id. +- Handoff evidence: `bc955459046c19a31fe00195b32f37f25a04e24f`. +- The final live-reconciliation commit is recorded in the PR phase comment because an artifact + cannot contain its own commit id. diff --git a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/final-handoff.md b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/final-handoff.md index 26ca1f8e94..a0918f7fae 100644 --- a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/final-handoff.md +++ b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/final-handoff.md @@ -9,9 +9,10 @@ | Base | `origin/main` at `fac9e339042c5394bf882311657d8981d353a1c3` | | Formal cycle-1 verdict | `FAIL_PLAN / CHANGES_REQUESTED`; `plan-eval.md` at `f1a29fe1a65d59f71a59bf4b6b2a48fc49e1e86f` | | Reviewable remediation commit | `78a7cecd1d5eaafa7a65bc25a21af497567128dc` | +| Verified remote handoff HEAD | `bc955459046c19a31fe00195b32f37f25a04e24f` | | RFC | `rfcs/0000-sdk-client-contributions.md` (`0000`, Draft) | | Run dir | `.llm/runs/docs-rfc-sdk-client-contribution--rfc/` | -| Requested lifecycle | exactly one `status:plan-eval` after push | +| Verified lifecycle | exactly one `status:plan-eval` | The PR stays draft. This is author remediation of authoritative Fable findings F-A1 through F-A10, not a self-evaluation or PASS claim. No RFC number, issue, milestone, merge, evaluator, or product @@ -54,16 +55,16 @@ implementation, and upstream-major-neutral public/generated RFC-A declarations. ## Validation Evidence -| Gate | Evidence | -| ------------------------------ | ---------------------------------------------------------------------- | -| Real-surface type fixture | PASS — Deno check exit 0; 0.92 s/268,448 KiB informational observation | -| Targeted format/lint | PASS — 9 files checked; fixture lint 1 file/0 findings | -| Focused RFC links | PASS — 1 document, 0 broken links/anchors | -| Repository docs links/accuracy | PASS — 102 documents/0 broken; accuracy PASS | -| Doctrine | PASS — `deno task arch:check` exit 0; warning-only baseline unchanged | -| Diff hygiene | PASS — `git diff --check` | -| Review threads | PASS — 0 total / 0 unanswered | -| Git/PR metadata | `VALIDATION_PENDING` | +| Gate | Evidence | +| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------ | +| Real-surface type fixture | PASS — Deno check exit 0; 0.92 s/268,448 KiB informational observation | +| Targeted format/lint | PASS — 9 files checked; fixture lint 1 file/0 findings | +| Focused RFC links | PASS — 1 document, 0 broken links/anchors | +| Repository docs links/accuracy | PASS — 102 documents/0 broken; accuracy PASS | +| Doctrine | PASS — `deno task arch:check` exit 0; warning-only baseline unchanged | +| Diff hygiene | PASS — `git diff --check` | +| Review threads | PASS — 0 total / 0 unanswered | +| Git/PR metadata | PASS — explicit-refspec push; draft/main; required labels; sole `status:plan-eval`; milestone null; #1348 reference only | No CLI/scaffold runtime E2E is appropriate for this RFC-only change; implementation stages retain the full runtime gates. Existing JSR/doc-lint baselines remain recorded in `research.md` and are not diff --git a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/supervisor.md b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/supervisor.md index c959fea33c..fadd348447 100644 --- a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/supervisor.md +++ b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/supervisor.md @@ -47,7 +47,9 @@ Written at run start per `workflow/lane-policy.md` § Supervisor identity. - Reviewable amended RFC/research commit: `7a0d398087a6608ff1a55bb9fe4c47158edb72a7`. - Formal evaluator artifact: `f1a29fe1a65d59f71a59bf4b6b2a48fc49e1e86f`; verdict SHA-256 `0690af2a2914ad0a9118be04ccebb933af33b2bac8f3f743bc7990f8f5f38cdd`. -- The remediated RFC returns to `status:plan-eval` only after focused gates, meaningful commits, an - explicit-refspec push, and a structured cycle-2 handoff comment. +- Reviewable remediation: `78a7cecd1d5eaafa7a65bc25a21af497567128dc`; verified remote handoff HEAD + before final metadata: `bc955459046c19a31fe00195b32f37f25a04e24f`. +- The remediated RFC passed focused gates, was pushed by explicit refspec, and has returned to + exactly one `status:plan-eval`; the structured cycle-2 handoff comment records final HEAD. - The exact Fable cycle-2 entry point and prohibited mutations are in `final-handoff.md`. No evaluator was launched and no PASS verdict is claimed by this session. diff --git a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/worklog.md b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/worklog.md index 0905da2b43..8acc1ab1c1 100644 --- a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/worklog.md +++ b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/worklog.md @@ -193,6 +193,8 @@ considered complete. | 2026-08-08 | 5 | design remediation | Scoped the zero-upstream gate; completed key/default/reconnect/Desktop/private-port/context laws; corrected v2 GET/OTel/lock gates; reconciled #1350 Stage 1a versus metadata Stage 1b. | | 2026-08-08 | 5 | focused validation | Targeted Markdown/TypeScript format, fixture lint/check, focused and 102-document links, docs accuracy, doctrine, and diff hygiene all exit 0; warning-only doctrine/dependency baseline is unchanged. | | 2026-08-08 | 5 | remediation commit | Committed the RFC, in-tree type fixture, and author-owned harness correction as `78a7cecd1d5eaafa7a65bc25a21af497567128dc`. | +| 2026-08-08 | 5 | handoff push | Committed handoff evidence as `bc955459046c19a31fe00195b32f37f25a04e24f` and pushed only with `HEAD:refs/heads/docs/rfc-sdk-client-contribution`; remote advanced from `f1a29fe1a` to `bc9554590`. | +| 2026-08-08 | 5 | PR reconciliation | Replaced the stale body with cycle-1 corrections/evidence; preserved draft/main and #1348 reference-only; restored all required labels with exactly one lifecycle `status:plan-eval`; milestone remains null. | ## Decisions @@ -263,10 +265,13 @@ considered complete. | Cycle-1 repository docs | `deno task docs:links`; `deno task docs:accuracy` | PASS, 102 docs/0 broken; accuracy PASS | | Cycle-1 doctrine | `deno task arch:check` | PASS, exit 0; warning-only dependency/doctrine baseline unchanged | | Cycle-1 diff hygiene | `git diff --check` | PASS | +| Cycle-1 review threads | `deno task agentic:review-threads -- --repo rickylabs/netscript --pr 1390 --pretty` | PASS, 0 total / 0 unanswered | +| Cycle-1 PR metadata | live `gh pr view 1390` | PASS, draft/main, required labels, exactly one `status:plan-eval`, milestone null, #1348 reference only | +| Cycle-1 explicit push | `git push origin HEAD:refs/heads/docs/rfc-sdk-client-contribution` | PASS, `f1a29fe1a..bc9554590` | Cycle-1 remediation validation, commits, explicit-refspec push, and live PR reconciliation are -recorded below after the verdict commands complete. External Fable cycle 2 and later Qwen verdicts -remain pending by owner instruction; this author does not self-approve or launch them. +complete. External Fable cycle 2 and later Qwen verdicts remain pending by owner instruction; this +author does not self-approve or launch them. ## Handoff Notes From 9f45404acaf97a1593ee8fd1aea098626dfb3691 Mon Sep 17 00:00:00 2001 From: Rickylabs Date: Sat, 8 Aug 2026 20:58:37 +0200 Subject: [PATCH 10/12] docs(harness): close aggregate RFC diff hygiene --- .../final-handoff.md | 2 +- .../implement.md | 31 +++++++++++-------- .../worklog.md | 2 ++ 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/final-handoff.md b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/final-handoff.md index a0918f7fae..6d7abb66e7 100644 --- a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/final-handoff.md +++ b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/final-handoff.md @@ -62,7 +62,7 @@ implementation, and upstream-major-neutral public/generated RFC-A declarations. | Focused RFC links | PASS — 1 document, 0 broken links/anchors | | Repository docs links/accuracy | PASS — 102 documents/0 broken; accuracy PASS | | Doctrine | PASS — `deno task arch:check` exit 0; warning-only baseline unchanged | -| Diff hygiene | PASS — `git diff --check` | +| Diff hygiene | PASS — working-tree and aggregate `origin/main...HEAD`; one original `implement.md` trailing blank corrected | | Review threads | PASS — 0 total / 0 unanswered | | Git/PR metadata | PASS — explicit-refspec push; draft/main; required labels; sole `status:plan-eval`; milestone null; #1348 reference only | diff --git a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/implement.md b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/implement.md index 96cb4868bd..74a5e1e384 100644 --- a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/implement.md +++ b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/implement.md @@ -9,21 +9,27 @@ permissions. Do not create a rival session or delegate the core RFC authorship. ## SKILL -- `netscript-harness` — activate the full harness and RFC/docs design run; maintain every mandatory run artifact. -- `netscript-doctrine` — evaluate the proposed public SDK/plugin extension seam against axioms, extension-axis law, layering, anti-patterns, and debt. -- `netscript-pr` — open and maintain a draft RFC PR to `main`, with correct labels, phase comments, and no premature merge/closure. +- `netscript-harness` — activate the full harness and RFC/docs design run; maintain every mandatory + run artifact. +- `netscript-doctrine` — evaluate the proposed public SDK/plugin extension seam against axioms, + extension-axis law, layering, anti-patterns, and debt. +- `netscript-pr` — open and maintain a draft RFC PR to `main`, with correct labels, phase comments, + and no premature merge/closure. - `netscript-tools` — use repo-native validation and compact evidence tooling. -- `netscript-deno-toolchain` — inspect current public APIs through `deno doc` and native dependency/package tools rather than assumptions. +- `netscript-deno-toolchain` — inspect current public APIs through `deno doc` and native + dependency/package tools rather than assumptions. - `jsr-audit` — assess export and publish-surface consequences of the proposed SDK seam. - `rtk` — reduce read-heavy command output without changing semantics. -- `codex-wsl-remote` — preserve the daemon-attached, mobile-visible session and explicit-refspec push safety. +- `codex-wsl-remote` — preserve the daemon-attached, mobile-visible session and explicit-refspec + push safety. ## Objective Turn Claude Fable 5's RFC-A proposal into the actual lightweight RFC required by `rfcs/README.md`. The input is a starting proposal, not ground truth: -- proposal: `/home/codex/repos/netscript-fable5-remediation-plan/.llm/runs/plan-fable5-remediation-roadmap--seed/fable-5-remediation-plan/rfcs/RFC-A-sdk-client-composition.md` +- proposal: + `/home/codex/repos/netscript-fable5-remediation-plan/.llm/runs/plan-fable5-remediation-roadmap--seed/fable-5-remediation-plan/rfcs/RFC-A-sdk-client-composition.md` - tracking issue: `#1348` - related filed issues: `#1349`–`#1353`, plus live dependencies named by the proposal - source roadmap PR: `#1347` @@ -46,18 +52,18 @@ unhidden or composed. plan gate, and evaluator protocol completely. 2. Produce `rfcs/0000-sdk-client-contributions.md` from `rfcs/0000-template.md`, keeping `0000` until maintainer acceptance. The RFC must be decision-complete enough to implement: motivation, - terminology, exact public/type-level surface with realistic examples, invariants, composition - and ordering law, security/privacy and redaction, compatibility/migration, rejected alternatives, + terminology, exact public/type-level surface with realistic examples, invariants, composition and + ordering law, security/privacy and redaction, compatibility/migration, rejected alternatives, unresolved questions safe for FCP, staged implementation plan, conformance/fitness gates, docs/scaffold implications, and issue/epic decomposition. 3. Treat Claude's prose as a design pack to challenge. Cite repository paths/symbols and primary upstream sources where relevant. Use focused type probes or non-product scratch proofs when they materially validate inference/ergonomics; do not implement framework code in this RFC PR. 4. Make an initial harness/bootstrap commit, push only with an explicit refspec, and open a draft PR - against `main` in the same session. The PR must reference `#1348` without closing it, carry `rfc`, - `type:docs`, `area:sdk`, `area:plugins`, `priority:p1`, `ci:skip-e2e`, `ci:skip-scaffold`, and - exactly one lifecycle status. Move it to `status:plan-eval` only when the RFC is ready for Fable - review. Never assign an RFC number, merge, create/close issues, or mutate milestones. + against `main` in the same session. The PR must reference `#1348` without closing it, carry + `rfc`, `type:docs`, `area:sdk`, `area:plugins`, `priority:p1`, `ci:skip-e2e`, `ci:skip-scaffold`, + and exactly one lifecycle status. Move it to `status:plan-eval` only when the RFC is ready for + Fable review. Never assign an RFC number, merge, create/close issues, or mutate milestones. 5. Commit in coherent slices with run-artifact updates and PR phase comments. Run the docs/RFC gates that actually apply and record exact evidence. Do not trigger PLAN-EVAL/IMPL-EVAL yourself: the root orchestrator will steer the existing Claude Fable 5 session for the cross-RFC review, then @@ -70,4 +76,3 @@ Quality bar: this must be a real architecture RFC that a maintainer can ratify a can execute without guessing—not a lightly edited copy of Claude's draft. Preserve NetScript's mission: maximum end-to-end type safety, thin composable seams, generated ergonomics, plugin-owned extensions, observable failure, and no hidden magic. - diff --git a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/worklog.md b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/worklog.md index 8acc1ab1c1..e946492819 100644 --- a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/worklog.md +++ b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/worklog.md @@ -195,6 +195,7 @@ considered complete. | 2026-08-08 | 5 | remediation commit | Committed the RFC, in-tree type fixture, and author-owned harness correction as `78a7cecd1d5eaafa7a65bc25a21af497567128dc`. | | 2026-08-08 | 5 | handoff push | Committed handoff evidence as `bc955459046c19a31fe00195b32f37f25a04e24f` and pushed only with `HEAD:refs/heads/docs/rfc-sdk-client-contribution`; remote advanced from `f1a29fe1a` to `bc9554590`. | | 2026-08-08 | 5 | PR reconciliation | Replaced the stale body with cycle-1 corrections/evidence; preserved draft/main and #1348 reference-only; restored all required labels with exactly one lifecycle `status:plan-eval`; milestone remains null. | +| 2026-08-08 | 5 | aggregate hygiene | Base-to-HEAD `git diff --check` exposed one trailing blank line in the original run `implement.md`; removed it so the complete RFC branch diff, not only this slice, passes. | ## Decisions @@ -265,6 +266,7 @@ considered complete. | Cycle-1 repository docs | `deno task docs:links`; `deno task docs:accuracy` | PASS, 102 docs/0 broken; accuracy PASS | | Cycle-1 doctrine | `deno task arch:check` | PASS, exit 0; warning-only dependency/doctrine baseline unchanged | | Cycle-1 diff hygiene | `git diff --check` | PASS | +| Cycle-1 aggregate diff | `git diff --check origin/main...HEAD` after bootstrap-artifact whitespace correction | PASS | | Cycle-1 review threads | `deno task agentic:review-threads -- --repo rickylabs/netscript --pr 1390 --pretty` | PASS, 0 total / 0 unanswered | | Cycle-1 PR metadata | live `gh pr view 1390` | PASS, draft/main, required labels, exactly one `status:plan-eval`, milestone null, #1348 reference only | | Cycle-1 explicit push | `git push origin HEAD:refs/heads/docs/rfc-sdk-client-contribution` | PASS, `f1a29fe1a..bc9554590` | From 14b5c858cbead4aabe06e991528d8e9eaaaca7dc Mon Sep 17 00:00:00 2001 From: Rickylabs Date: Sat, 8 Aug 2026 21:01:16 +0200 Subject: [PATCH 11/12] =?UTF-8?q?docs(harness):=20PLAN-EVAL=20cycle=202=20?= =?UTF-8?q?=E2=80=94=20RFC-A=20PASS/APPROVED?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All F-A1..F-A10 verified resolved at 78a7cecd1; fixture independently type-checked (exit 0); lane audit adds type:test alongside type:docs. Co-Authored-By: Claude Fable 5 --- .../plan-eval.md | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/plan-eval.md b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/plan-eval.md index 38143d8f4c..9ecb603e69 100644 --- a/.llm/runs/docs-rfc-sdk-client-contribution--rfc/plan-eval.md +++ b/.llm/runs/docs-rfc-sdk-client-contribution--rfc/plan-eval.md @@ -1,5 +1,54 @@ # PLAN-EVAL — docs-rfc-sdk-client-contribution--rfc (RFC-A, PR #1390) +## CYCLE 2 — VERDICT: **PASS** (PR vocabulary: APPROVED) — 2026-08-08 + +Evaluator: same owner-designated Fable 5 · high session as cycle 1. Evaluated: RFC @ remediation +commit `78a7cecd1` (branch HEAD `4978f7d84`), fixture +`packages/sdk/tests/type-fixtures/sdk-client-contributions-rfc_type.ts`, updated +research/plan/worklog/drift/final-handoff. Independent evidence executed by the evaluator (not +taken from the author): `deno check --unstable-kv ` → exit 0; section-level verification +of every finding anchor against the amended text and worktree source. + +### Mechanical re-evaluation F-A1…F-A10 + +| # | Cycle-2 status | Evidence (amended RFC) | +| --- | --- | --- | +| F-A1 | **RESOLVED** | Declaration gate filters `deno doc --json` to named RFC-A symbols; generated files scanned in full; pre-existing `~orpc`/contracts paths are a **non-growing allowlist tied to #1278/#1350** and explicitly do not exempt new symbols (§Compatibility, L1243-1253) | +| F-A2 | **RESOLVED** | New §"Server key algebra and compatibility": default exact three-tuple preserved, partitioned five-tuple `['$netscript.sdk-context', serializedPairs]`, all six surfaces dispositioned in a normative table incl. `CacheKey`/key-bridge/persister/collections; recursive TanStack wrapping cost stated (cast fast-path only for the empty specialization); upstream-assignability fixture dispositioned (default `Record` keeps it valid) | +| F-A3 | **RESOLVED** | Compatibility defaults on every widened public generic (`ServiceClientMethod`/`ServiceClient`/`ServiceRequestRest` = `ServiceClientContext`; query/context types = `Record`; default table at L680-700) | +| F-A4 | **RESOLVED** | Logical-call-**epoch** model: iterator-phase reconnect = new epoch, contribution preparation rerun exactly once per epoch; mandatory stream fixture asserts preparation count 2, credential A→B across epochs, byte-equality within each (L917-929). Kills the frozen-credential path while preserving prepare-once | +| F-A5 | **RESOLVED** | §Desktop transport boundary: explicitly out of scope; `CreateDesktopServiceClientOptions` rejects `contributions` (excess-property + runtime `SDK_CONTRIBUTION_TRANSPORT_UNSUPPORTED`); targets exclude desktop; generators fail; docs obligation stated (L983-995) | +| F-A6 | **RESOLVED** | Ports live in `packages/sdk/src/internal/client-contributions/` (named files, no barrel, not in exports); absence asserted for every doc graph + a packed-consumer negative that rejects the internal specifier (L491-496, L1364-1369) | +| F-A7 | **RESOLVED** | Contributions now see only their **declared-context projection** + `signal`; the seven framework keys are reserved and a contribution declaring them is rejected; snapshot gate re-worded to the projection; forced-retry fixture drives `context.retry: 1`; private prepared-call channel named (L478-486) | +| F-A8 | **RESOLVED** | GET direction corrected: "Stable v1 already infers GET… the v2 spike must preserve GET (replacement inference + `allowMethods` + Sec-Fetch CSRF) or retire GET and replace dedupe; silently accepting POST-only while leaving the GET-only dedupe filter installed is not acceptable" (L1017-1025); `inferRPCMethodFromContractRouter` replacement in the v2 gates (L1299); OTel package selection assigned to #1351 (v1); lock-only family pinning stated (L1260) | +| F-A9 | **RESOLVED** | Fixture committed in-tree, imports the real `ContractLike`/`defineServices`/`ServiceQueryUtils`/key/desktop surfaces, pins default assignability + contribution inference + 16-accept/17-reject (`@ts-expect-error`); **evaluator re-executed the check: exit 0** | +| F-A10 | **RESOLVED** | v1.14.6 per-attempt header fact + header-safe dedupe cited (L931-932); raw-input sensitivity stated; #1350 Stage 1a (filed `safe()` scope) / Stage 1b (metadata) split recorded | + +### Lane/label honesty audit (evaluator-ordered) + +The PR now carries `packages/sdk/tests/type-fixtures/sdk-client-contributions-rfc_type.ts` — a +compile-only source-tree test fixture. Ruling: `ci:skip-e2e`/`ci:skip-scaffold` **remain valid** +(no runtime, generator, scaffold, export, or lock change; the proportionate gate is the scoped +type-check, which both the author and this evaluator executed). `type:docs` alone under-describes +the diff: the evaluator **adds `type:test`** alongside it (label authority granted). Not a +blocking finding. Merge-readiness note: the docs-lane CI skip does not itself compile the +fixture; the fixture check stays a recorded PR-body gate. + +### Residual advisories (non-blocking, for FCP/numbering) + +1. Frontmatter conventions differ across the pair: RFC-A `target-milestone: 0.0.7` + (implementation) vs RFC-B `0.0.6` (ratification, now footnoted). Harmonize at numbering time. +2. The eight FCP questions are all safe as posed (Q6's GET fork now correctly v2-owned). + +**PASS.** The plan is implementable without guessing; auth + locale still require no parallel +framework. Hard-stop lifted for stages 0–2 pending owner ratification and the root-owned Qwen +adversarial acceptance pass. Accepted content SHA of record: **`78a7cecd1d5eaafa7a65bc25a21af497567128dc`** +(branch HEAD `4978f7d844f05dae9c3236cd830a2b3c5b693dda`). + +--- + +# Cycle 1 record (2026-08-08, superseded by the PASS above) + | Field | Value | | --- | --- | | Verdict | **FAIL_PLAN** (PR-comment vocabulary: CHANGES_REQUESTED) — cycle 1 of 2 | From 418c4555a8fc15246b8a91e587bba69eeed6c64b Mon Sep 17 00:00:00 2001 From: Rickylabs Date: Tue, 11 Aug 2026 22:15:28 +0200 Subject: [PATCH 12/12] docs(rfc): accept typed SDK client contributions as RFC 0001 --- ...ient-contributions.md => 0001-sdk-client-contributions.md} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename rfcs/{0000-sdk-client-contributions.md => 0001-sdk-client-contributions.md} (99%) diff --git a/rfcs/0000-sdk-client-contributions.md b/rfcs/0001-sdk-client-contributions.md similarity index 99% rename from rfcs/0000-sdk-client-contributions.md rename to rfcs/0001-sdk-client-contributions.md index 4c6a2d882e..f00863b550 100644 --- a/rfcs/0000-sdk-client-contributions.md +++ b/rfcs/0001-sdk-client-contributions.md @@ -1,7 +1,7 @@ --- -rfc: 0000 +rfc: 0001 title: Typed SDK client contributions -status: Draft +status: Accepted authors: ['@rickylabs'] created: 2026-08-08 tracking-issue: https://github.com/rickylabs/netscript/issues/1348