@glubean/sdk 0.2.1 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. package/dist/bootstrap-registry.d.ts +38 -0
  2. package/dist/bootstrap-registry.d.ts.map +1 -0
  3. package/dist/bootstrap-registry.js +54 -0
  4. package/dist/bootstrap-registry.js.map +1 -0
  5. package/dist/configure/http.d.ts +25 -0
  6. package/dist/configure/http.d.ts.map +1 -0
  7. package/dist/configure/http.js +88 -0
  8. package/dist/configure/http.js.map +1 -0
  9. package/dist/configure/index.d.ts +78 -0
  10. package/dist/configure/index.d.ts.map +1 -0
  11. package/dist/configure/index.js +78 -0
  12. package/dist/configure/index.js.map +1 -0
  13. package/dist/configure/plugin.d.ts +23 -0
  14. package/dist/configure/plugin.d.ts.map +1 -0
  15. package/dist/configure/plugin.js +81 -0
  16. package/dist/configure/plugin.js.map +1 -0
  17. package/dist/configure/runtime.d.ts +24 -0
  18. package/dist/configure/runtime.d.ts.map +1 -0
  19. package/dist/configure/runtime.js +45 -0
  20. package/dist/configure/runtime.js.map +1 -0
  21. package/dist/configure/template.d.ts +22 -0
  22. package/dist/configure/template.d.ts.map +1 -0
  23. package/dist/configure/template.js +34 -0
  24. package/dist/configure/template.js.map +1 -0
  25. package/dist/configure/vars.d.ts +20 -0
  26. package/dist/configure/vars.d.ts.map +1 -0
  27. package/dist/configure/vars.js +48 -0
  28. package/dist/configure/vars.js.map +1 -0
  29. package/dist/configure.d.ts +2 -133
  30. package/dist/configure.d.ts.map +1 -1
  31. package/dist/configure.js +2 -436
  32. package/dist/configure.js.map +1 -1
  33. package/dist/contract-artifacts.d.ts +268 -0
  34. package/dist/contract-artifacts.d.ts.map +1 -0
  35. package/dist/contract-artifacts.js +402 -0
  36. package/dist/contract-artifacts.js.map +1 -0
  37. package/dist/contract-core.d.ts +43 -1
  38. package/dist/contract-core.d.ts.map +1 -1
  39. package/dist/contract-core.js +376 -5
  40. package/dist/contract-core.js.map +1 -1
  41. package/dist/contract-http/adapter.d.ts +1 -7
  42. package/dist/contract-http/adapter.d.ts.map +1 -1
  43. package/dist/contract-http/adapter.js +221 -199
  44. package/dist/contract-http/adapter.js.map +1 -1
  45. package/dist/contract-http/factory.d.ts.map +1 -1
  46. package/dist/contract-http/factory.js +13 -14
  47. package/dist/contract-http/factory.js.map +1 -1
  48. package/dist/contract-http/index.d.ts +1 -0
  49. package/dist/contract-http/index.d.ts.map +1 -1
  50. package/dist/contract-http/index.js +1 -0
  51. package/dist/contract-http/index.js.map +1 -1
  52. package/dist/contract-http/openapi.d.ts +56 -7
  53. package/dist/contract-http/openapi.d.ts.map +1 -1
  54. package/dist/contract-http/openapi.js +371 -21
  55. package/dist/contract-http/openapi.js.map +1 -1
  56. package/dist/contract-http/types.d.ts +72 -24
  57. package/dist/contract-http/types.d.ts.map +1 -1
  58. package/dist/contract-http/types.js +45 -1
  59. package/dist/contract-http/types.js.map +1 -1
  60. package/dist/contract-types.d.ts +270 -30
  61. package/dist/contract-types.d.ts.map +1 -1
  62. package/dist/expect.d.ts +13 -0
  63. package/dist/expect.d.ts.map +1 -1
  64. package/dist/expect.js +18 -0
  65. package/dist/expect.js.map +1 -1
  66. package/dist/index.d.ts +57 -10
  67. package/dist/index.d.ts.map +1 -1
  68. package/dist/index.js +15 -8
  69. package/dist/index.js.map +1 -1
  70. package/dist/install-plugin.d.ts +94 -0
  71. package/dist/install-plugin.d.ts.map +1 -0
  72. package/dist/install-plugin.js +222 -0
  73. package/dist/install-plugin.js.map +1 -0
  74. package/dist/internal.d.ts +2 -0
  75. package/dist/internal.d.ts.map +1 -1
  76. package/dist/internal.js +8 -0
  77. package/dist/internal.js.map +1 -1
  78. package/dist/plugin.d.ts +45 -34
  79. package/dist/plugin.d.ts.map +1 -1
  80. package/dist/plugin.js +47 -34
  81. package/dist/plugin.js.map +1 -1
  82. package/dist/runner-input-channel.d.ts +95 -0
  83. package/dist/runner-input-channel.d.ts.map +1 -0
  84. package/dist/runner-input-channel.js +110 -0
  85. package/dist/runner-input-channel.js.map +1 -0
  86. package/dist/{test-builder.d.ts → test/builder.d.ts} +2 -2
  87. package/dist/test/builder.d.ts.map +1 -0
  88. package/dist/{test-builder.js → test/builder.js} +3 -3
  89. package/dist/{test-builder.js.map → test/builder.js.map} +1 -1
  90. package/dist/{each-builder.d.ts → test/each-builder.d.ts} +1 -1
  91. package/dist/test/each-builder.d.ts.map +1 -0
  92. package/dist/{each-builder.js → test/each-builder.js} +3 -3
  93. package/dist/test/each-builder.js.map +1 -0
  94. package/dist/{test-extend.d.ts → test/extend.d.ts} +3 -3
  95. package/dist/test/extend.d.ts.map +1 -0
  96. package/dist/{test-extend.js → test/extend.js} +5 -5
  97. package/dist/test/extend.js.map +1 -0
  98. package/dist/{test-utils.d.ts → test/utils.d.ts} +2 -2
  99. package/dist/test/utils.d.ts.map +1 -0
  100. package/dist/{test-utils.js → test/utils.js} +1 -1
  101. package/dist/test/utils.js.map +1 -0
  102. package/dist/types.d.ts +78 -7
  103. package/dist/types.d.ts.map +1 -1
  104. package/package.json +1 -1
  105. package/dist/contract-http/flow-helpers.d.ts +0 -12
  106. package/dist/contract-http/flow-helpers.d.ts.map +0 -1
  107. package/dist/contract-http/flow-helpers.js +0 -34
  108. package/dist/contract-http/flow-helpers.js.map +0 -1
  109. package/dist/contract-http/markdown.d.ts +0 -10
  110. package/dist/contract-http/markdown.d.ts.map +0 -1
  111. package/dist/contract-http/markdown.js +0 -21
  112. package/dist/contract-http/markdown.js.map +0 -1
  113. package/dist/each-builder.d.ts.map +0 -1
  114. package/dist/each-builder.js.map +0 -1
  115. package/dist/test-builder.d.ts.map +0 -1
  116. package/dist/test-extend.d.ts.map +0 -1
  117. package/dist/test-extend.js.map +0 -1
  118. package/dist/test-utils.d.ts.map +0 -1
  119. package/dist/test-utils.js.map +0 -1
@@ -10,7 +10,7 @@
10
10
  * ContractCase, ContractExpect, etc.).
11
11
  */
12
12
  import type { HttpClient, SchemaLike, TestContext } from "../types.js";
13
- import type { CaseDefaultRun, CaseRequires, CaseSeverity, Extensions } from "../contract-types.js";
13
+ import type { BaseCaseSpec, Extensions } from "../contract-types.js";
14
14
  /**
15
15
  * HTTP security scheme declaration for contract instances.
16
16
  * Maps to OpenAPI `securitySchemes`. Authoritative metadata, not docs-only.
@@ -69,7 +69,64 @@ export interface ContractExpect<T = unknown> {
69
69
  /** Named response examples (OpenAPI docs). */
70
70
  examples?: Record<string, ContractExample<T>>;
71
71
  }
72
- export interface ContractCase<T = unknown, S = void> {
72
+ /**
73
+ * Static-body shape for HTTP case `body` field. Excludes `unknown` (which
74
+ * would swallow the function branch in a union and lose `Needs` typing for
75
+ * function-valued bodies). Function-form `body: (input: Needs) => ...` only
76
+ * matches when the static-form types reject the value.
77
+ */
78
+ export type HttpStaticBody = Record<string, unknown> | unknown[] | string | number | boolean | null | FormData | URLSearchParams | Blob;
79
+ /**
80
+ * v0 HTTP case factory — closes the v3 P2 known-open ("HTTP body Needs
81
+ * drift"). Inside a contract spec literal, TypeScript can't correlate
82
+ * `needs: SchemaLike<X>` and `body: (input: Y) => ...` from sibling
83
+ * fields — author can write drift between them and TS won't flag it
84
+ * (`body` runs with `input.email` undefined when `body` destructures
85
+ * a key that isn't on Needs).
86
+ *
87
+ * `defineHttpCase<Needs, T>` captures `Needs` once via the explicit
88
+ * generic; the case literal is then checked against
89
+ * `ContractCase<T, Needs>` so all action fields (`body`, `params`,
90
+ * `query`, `headers`) are constrained to `(input: Needs) => ...`. Drift
91
+ * between `needs` and any action field becomes a compile error.
92
+ *
93
+ * Use it for cases that declare `needs` AND have function-valued action
94
+ * fields. Cases without `needs` (or with only static action fields)
95
+ * don't need the factory; the runtime invariants are unaffected either
96
+ * way (this is a typing improvement only).
97
+ *
98
+ * @example
99
+ * ```ts
100
+ * import { defineHttpCase } from "@glubean/sdk";
101
+ * import { z } from "zod";
102
+ *
103
+ * const successCase = defineHttpCase<{ email: string }>({
104
+ * description: "creates a user",
105
+ * needs: z.object({ email: z.string() }),
106
+ * // body, params, query, headers params now type-checked against
107
+ * // { email: string } — author can NOT write `({wrongKey}) => ...`.
108
+ * body: ({ email }) => ({ email }),
109
+ * expect: { status: 201 },
110
+ * });
111
+ *
112
+ * const api = contract.http.with("users", { client });
113
+ * export const createUser = api("user.create", {
114
+ * endpoint: "POST /users",
115
+ * cases: { success: successCase },
116
+ * });
117
+ * ```
118
+ *
119
+ * @param c The case spec to validate. Returned verbatim.
120
+ */
121
+ export declare function defineHttpCase<Needs = void, T = unknown>(c: ContractCase<T, Needs>): ContractCase<T, Needs>;
122
+ export interface ContractCase<T = unknown, Needs = void> extends BaseCaseSpec {
123
+ /**
124
+ * Per-case logical input schema. Redeclares the `BaseCaseSpec.needs` field
125
+ * with the case-specific `Needs` parameter so author-provided schema and
126
+ * function-valued action field parameter types stay locked together —
127
+ * preventing drift between `needs: SchemaLike<X>` and `body: ({wrong}) => ...`.
128
+ */
129
+ needs?: SchemaLike<Needs>;
73
130
  /** Per-case HTTP client override. */
74
131
  client?: HttpClient;
75
132
  /** Why this case exists — required. */
@@ -77,35 +134,26 @@ export interface ContractCase<T = unknown, S = void> {
77
134
  /** Expected response. */
78
135
  expect: ContractExpect<T>;
79
136
  /**
80
- * Request body (for POST/PUT/PATCH). Static value, FormData/URLSearchParams
81
- * /Blob/string for non-JSON content types, or a function of setup state.
137
+ * Request body (for POST/PUT/PATCH). Either a static value (HttpStaticBody)
138
+ * or a function of the case's logical input (matching `needs`). v10
139
+ * attachment model: no more setup state — input comes from overlay
140
+ * bootstrap, explicit `--input-json`, or flow `.step() in` lens.
141
+ *
142
+ * The static branch deliberately uses concrete types (not `unknown`)
143
+ * because `unknown` in a union swallows the function branch — `Needs`
144
+ * typing on the function param would then be silently bypassed.
82
145
  */
83
- body?: unknown | FormData | URLSearchParams | Blob | ((state: S) => unknown);
146
+ body?: HttpStaticBody | ((input: Needs) => unknown);
84
147
  /** Request content type override for this case. */
85
148
  contentType?: string;
86
149
  /** URL params. Values can be `ParamValue` objects for OpenAPI metadata. */
87
- params?: Record<string, ParamValue> | ((state: S) => Record<string, string>);
150
+ params?: Record<string, ParamValue> | ((input: Needs) => Record<string, string>);
88
151
  /** Query parameters. */
89
- query?: Record<string, ParamValue> | ((state: S) => Record<string, string>);
152
+ query?: Record<string, ParamValue> | ((input: Needs) => Record<string, string>);
90
153
  /** Request headers merged with client headers. */
91
- headers?: Record<string, string> | ((state: S) => Record<string, string>);
92
- /** Setup runs before the request. Return value goes to param/query/body/headers functions + teardown. */
93
- setup?: (ctx: TestContext) => Promise<S>;
94
- /** Teardown runs after verify, even on failure. */
95
- teardown?: (ctx: TestContext, state: S) => Promise<void>;
154
+ headers?: Record<string, string> | ((input: Needs) => Record<string, string>);
96
155
  /** Business-logic verify — runs after status and schema validation. */
97
156
  verify?: (ctx: TestContext, res: T) => Promise<void>;
98
- /** Not yet executable; reason shown in skip message. */
99
- deferred?: string;
100
- /** Deprecated; value is the reason. */
101
- deprecated?: string;
102
- /** Additional tags (merged with contract-level tags). */
103
- tags?: string[];
104
- severity?: CaseSeverity;
105
- requires?: CaseRequires;
106
- defaultRun?: CaseDefaultRun;
107
- /** Per-case OpenAPI extensions. */
108
- extensions?: Extensions;
109
157
  }
110
158
  /**
111
159
  * Structured request specification. Can be a bare SchemaLike (JSON body
@@ -239,7 +287,7 @@ export interface HttpFlowCaseOutput {
239
287
  * `contract.http.with("name", defaults)`.
240
288
  */
241
289
  export interface HttpContractFactory {
242
- <Cases extends Record<string, ContractCase<any, any>>>(id: string, spec: HttpContractSpec<Cases>): import("../contract-types.js").ProtocolContract<HttpContractSpec, HttpPayloadSchemas, HttpContractMeta>;
290
+ <Cases extends Record<string, ContractCase<any, any>>>(id: string, spec: HttpContractSpec<Cases>): import("../contract-types.js").ProtocolContract<HttpContractSpec<Cases>, HttpPayloadSchemas, HttpContractMeta, Cases>;
243
291
  with(name: string, defaults: HttpContractDefaults): HttpContractFactory;
244
292
  }
245
293
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/contract-http/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/contract-http/types.ts"],"names":[],"mappings":"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"}
@@ -9,5 +9,49 @@
9
9
  * Source-of-truth for user-facing authoring types (HttpContractSpec,
10
10
  * ContractCase, ContractExpect, etc.).
11
11
  */
12
- export {};
12
+ /**
13
+ * v0 HTTP case factory — closes the v3 P2 known-open ("HTTP body Needs
14
+ * drift"). Inside a contract spec literal, TypeScript can't correlate
15
+ * `needs: SchemaLike<X>` and `body: (input: Y) => ...` from sibling
16
+ * fields — author can write drift between them and TS won't flag it
17
+ * (`body` runs with `input.email` undefined when `body` destructures
18
+ * a key that isn't on Needs).
19
+ *
20
+ * `defineHttpCase<Needs, T>` captures `Needs` once via the explicit
21
+ * generic; the case literal is then checked against
22
+ * `ContractCase<T, Needs>` so all action fields (`body`, `params`,
23
+ * `query`, `headers`) are constrained to `(input: Needs) => ...`. Drift
24
+ * between `needs` and any action field becomes a compile error.
25
+ *
26
+ * Use it for cases that declare `needs` AND have function-valued action
27
+ * fields. Cases without `needs` (or with only static action fields)
28
+ * don't need the factory; the runtime invariants are unaffected either
29
+ * way (this is a typing improvement only).
30
+ *
31
+ * @example
32
+ * ```ts
33
+ * import { defineHttpCase } from "@glubean/sdk";
34
+ * import { z } from "zod";
35
+ *
36
+ * const successCase = defineHttpCase<{ email: string }>({
37
+ * description: "creates a user",
38
+ * needs: z.object({ email: z.string() }),
39
+ * // body, params, query, headers params now type-checked against
40
+ * // { email: string } — author can NOT write `({wrongKey}) => ...`.
41
+ * body: ({ email }) => ({ email }),
42
+ * expect: { status: 201 },
43
+ * });
44
+ *
45
+ * const api = contract.http.with("users", { client });
46
+ * export const createUser = api("user.create", {
47
+ * endpoint: "POST /users",
48
+ * cases: { success: successCase },
49
+ * });
50
+ * ```
51
+ *
52
+ * @param c The case spec to validate. Returned verbatim.
53
+ */
54
+ export function defineHttpCase(c) {
55
+ return c;
56
+ }
13
57
  //# sourceMappingURL=types.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/contract-http/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/contract-http/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AA6GH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,MAAM,UAAU,cAAc,CAC5B,CAAyB;IAEzB,OAAO,CAAC,CAAC;AACX,CAAC"}
@@ -17,7 +17,8 @@
17
17
  * See `internal/40-discovery/proposals/contract-generics-complete.md` v5
18
18
  * and `internal/40-discovery/proposals/contract-flow.md` v9 for design.
19
19
  */
20
- import type { Test, TestContext } from "./types.js";
20
+ import type { SchemaLike, Test, TestContext } from "./types.js";
21
+ import type { KnownArtifacts, KnownArtifactParts, KnownArtifactOptions } from "./index.js";
21
22
  /**
22
23
  * Case lifecycle.
23
24
  *
@@ -73,6 +74,89 @@ export interface FailureClassification {
73
74
  retryable?: boolean;
74
75
  message?: string;
75
76
  }
77
+ /**
78
+ * Minimum shape every case spec must satisfy. Adapter-specific case specs
79
+ * (HttpContractCase / GrpcContractCase / GraphqlContractCase / ...) extend
80
+ * this with protocol-specific fields.
81
+ *
82
+ * Core (`dispatchContract`) reads these fields directly from `spec.cases[key]`.
83
+ * Adapter-specific fields are opaque to core and passed through to the adapter.
84
+ *
85
+ * @see contract-attachment-model.md v1.3 for `needs` / `given` / `runnability` semantics.
86
+ */
87
+ export interface BaseCaseSpec {
88
+ description?: string;
89
+ /**
90
+ * Logical input schema for the case. The only public input contract.
91
+ * Protocol action fields (HTTP body/headers/params/query etc.) receive
92
+ * this typed input as their argument.
93
+ *
94
+ * Typed as `SchemaLike<unknown>` at the base to accept any concrete
95
+ * schema. The specific type is extracted per-case via `InferCaseInput<C>`
96
+ * when `ProtocolContract.case<K>()` types its return — TS infers the
97
+ * concrete T from the literal `SchemaLike<T>` the author wrote.
98
+ *
99
+ * This avoids a generic on `BaseCaseSpec<Needs>` which would force every
100
+ * adapter's case type (ContractCase / GrpcContractCase / GraphqlContractCase)
101
+ * to thread a Needs parameter through — too invasive for the authoring API.
102
+ */
103
+ needs?: SchemaLike<unknown>;
104
+ /**
105
+ * World-state precondition this case assumes. Projected as part of the
106
+ * contract because it changes what `expect` means (see §0.9 of the
107
+ * attachment model proposal). Bootstrap may *satisfy* `given` at
108
+ * runtime, but it must not be the only place where a semantically
109
+ * relevant precondition is declared.
110
+ */
111
+ given?: string;
112
+ /**
113
+ * Runnability metadata — grouped under `runnability` to make the
114
+ * "not contract semantic" stance structurally visible. Fields here
115
+ * do NOT enter contract projection; they enter runnable inventory.
116
+ */
117
+ runnability?: {
118
+ requireAttachment?: boolean;
119
+ };
120
+ deferred?: string;
121
+ deprecated?: string;
122
+ severity?: CaseSeverity;
123
+ requires?: CaseRequires;
124
+ defaultRun?: CaseDefaultRun;
125
+ tags?: string[];
126
+ extensions?: Extensions;
127
+ }
128
+ /**
129
+ * Context passed to `bootstrap.run(ctx, params)`. Extends TestContext with
130
+ * cleanup registration — cleanups run LIFO after standalone case execution,
131
+ * even if case expect/verify fails.
132
+ *
133
+ * Flow NEVER invokes bootstrap, so StandaloneBootstrapContext only exists
134
+ * for the standalone execution path.
135
+ */
136
+ export interface StandaloneBootstrapContext extends TestContext {
137
+ cleanup(fn: () => Promise<void> | void): void;
138
+ }
139
+ /**
140
+ * Bootstrap spec. Plain function form is shorthand for structured form
141
+ * with no `params`.
142
+ *
143
+ * Body is opaque (§4.2 attachment model); only `params` schema is projectable.
144
+ */
145
+ export type Bootstrap<Params, Output> = ((ctx: StandaloneBootstrapContext) => Promise<Output>) | {
146
+ params?: SchemaLike<Params>;
147
+ run: (ctx: StandaloneBootstrapContext, params: Params) => Promise<Output>;
148
+ };
149
+ /**
150
+ * Runtime marker carried by a registered bootstrap overlay. Scanner reads
151
+ * the __glubean_type discriminator; runner consults the registry at
152
+ * runnable resolution time.
153
+ */
154
+ export interface BootstrapAttachment<Needs = void, Params = void> {
155
+ readonly __glubean_type: "bootstrap-attachment";
156
+ readonly testId: string;
157
+ readonly __phantom_needs?: Needs;
158
+ readonly __phantom_params?: Params;
159
+ }
76
160
  /**
77
161
  * Protocol-agnostic case metadata. `schemas` is plugin-defined payload shape,
78
162
  * opaque to core.
@@ -97,6 +181,39 @@ export interface CaseMeta<PayloadSchemas = unknown, Meta = unknown> {
97
181
  schemas?: PayloadSchemas;
98
182
  /** Plugin-defined free-form metadata. Opaque to core. */
99
183
  meta?: Meta;
184
+ /**
185
+ * World-state precondition (contract-attachment-model.md §0.9). Projected
186
+ * as part of the contract because it changes what `expect` means.
187
+ * Adapter-independent — threaded verbatim from `BaseCaseSpec.given`.
188
+ */
189
+ given?: string;
190
+ /**
191
+ * Runnability metadata (contract-attachment-model.md §7.2). Not contract
192
+ * semantic; drives runnable inventory (e.g. `requireAttachment` blocks
193
+ * raw execution). Threaded verbatim from `BaseCaseSpec.runnability`.
194
+ */
195
+ runnability?: {
196
+ requireAttachment?: boolean;
197
+ };
198
+ /**
199
+ * v10 attachment-model — the case's logical-input (`needs`) schema in
200
+ * JSON-safe form. Populated by adapter.normalize() when the case's
201
+ * `needs` schema can be projected (`schemaToJsonSchema` returns
202
+ * something). Absent when the case has no `needs` OR when the schema
203
+ * shape isn't projectable (custom `safeParse`-only validator).
204
+ *
205
+ * To decide whether `rawBypass` is available, consumers should check
206
+ * `hasNeeds` below — it is true whenever the case declared `needs`
207
+ * regardless of whether the schema survives projection.
208
+ */
209
+ needsSchema?: unknown;
210
+ /**
211
+ * True iff the case declares `needs`. Independent from `needsSchema`
212
+ * (which may be undefined even when `hasNeeds` is true, e.g. opaque
213
+ * `safeParse`-only schemas). Inventory uses this to decide whether
214
+ * the `rawBypass` execution path should appear on an overlay.
215
+ */
216
+ hasNeeds?: boolean;
100
217
  }
101
218
  /**
102
219
  * Runtime contract projection — adapter.project() output.
@@ -157,8 +274,45 @@ export interface ContractProtocolAdapter<Spec = unknown, RuntimeSchemas = unknow
157
274
  * Execute a single case. Called by the core dispatcher for each spec case.
158
275
  * Adapter does the full case lifecycle: setup → request/invoke → expect →
159
276
  * verify → teardown.
277
+ *
278
+ * **Legacy path** — uses case-local `setup` / `teardown` fields.
279
+ * Replaced by `executeCase` in v10 attachment model (setup/teardown are
280
+ * removed from contract case surface; state is provided via bootstrap
281
+ * overlay or explicit input). Kept for backward compat during migration;
282
+ * removed in Spike 2 Phase 2c.
160
283
  */
161
284
  execute: (ctx: TestContext, caseSpec: unknown, contractSpec: Spec) => Promise<void>;
285
+ /**
286
+ * Execute a single case in **standalone mode** with an already-resolved
287
+ * logical input.
288
+ *
289
+ * Scope note: this method is **standalone-only**. Flow dispatch continues
290
+ * to use `executeCaseInFlow` (below). The two paths coexist because flow
291
+ * never invokes bootstrap (attachment model §14.0 non-negotiable invariant)
292
+ * — if executeCase took `mode: "flow"`, it would imply flow could route
293
+ * through here, which contradicts the invariant.
294
+ *
295
+ * v10 attachment model entry point. Core dispatcher calls this after:
296
+ * - resolving bootstrap overlay (if registered) to produce `resolvedInput`
297
+ * - OR receiving explicit `--input-json` / `input` from runner
298
+ * - validating against the case's `needs` schema
299
+ *
300
+ * Adapter responsibilities:
301
+ * 1. Receive already-validated `resolvedInput` (no re-validation needed)
302
+ * 2. Call function-valued action fields (body / headers / etc.) with the input
303
+ * 3. Execute request / expect / verify
304
+ * 4. No setup / teardown — those are gone in v10
305
+ *
306
+ * @see contract-attachment-model.md v1.3 §10.1
307
+ * @see single-case-execution-api.md v1 §5
308
+ */
309
+ executeCase?: (options: {
310
+ ctx: TestContext;
311
+ contract: ProtocolContract<Spec, SafeSchemas, SafeMeta>;
312
+ caseKey: string;
313
+ /** Logical input already validated against `needs`. `void` when case has no needs. */
314
+ resolvedInput: unknown;
315
+ }) => Promise<void>;
162
316
  /**
163
317
  * Project the spec to a Runtime projection (may contain live schemas).
164
318
  *
@@ -182,7 +336,17 @@ export interface ContractProtocolAdapter<Spec = unknown, RuntimeSchemas = unknow
182
336
  * protocol-agnostic skeleton (no `schemas` / `meta`). See `contract-flow.md`
183
337
  * §3.5.3 rule 3.
184
338
  */
185
- normalize?: (projection: ContractProjection<RuntimeSchemas, RuntimeMeta> & {
339
+ /**
340
+ * Convert the runtime projection (may contain live refs like Zod schemas)
341
+ * into the JSON-safe `Extracted` form consumed by downstream (scanner /
342
+ * MCP / CLI / cloud). SDK's `dispatchContract` calls this unconditionally
343
+ * at contract construction and stores the result on the carrier as
344
+ * `_extracted` — scanner reads that directly. Adapter is responsible for
345
+ * knowing which fields are schemas (convert Zod → JSON Schema) vs literal
346
+ * example data (pass through) vs protocol-specific metadata that must
347
+ * survive normalize (e.g. HTTP `security`).
348
+ */
349
+ normalize: (projection: ContractProjection<RuntimeSchemas, RuntimeMeta> & {
186
350
  id: string;
187
351
  }) => ExtractedContractProjection<SafeSchemas, SafeMeta>;
188
352
  /**
@@ -197,16 +361,23 @@ export interface ContractProtocolAdapter<Spec = unknown, RuntimeSchemas = unknow
197
361
  }>;
198
362
  }) => FailureClassification | undefined;
199
363
  /**
200
- * Optional: render contract as an OpenAPI fragment. Input is the Extracted
201
- * projection (after normalize). Used by MCP `glubean_openapi` tool.
202
- */
203
- toOpenApi?: (projection: ExtractedContractProjection<SafeSchemas, SafeMeta>) => Record<string, unknown> | undefined;
204
- /**
205
- * Optional: render contract as Markdown documentation. Used by
206
- * CLI `glubean contracts --format md-outline` and
207
- * MCP `glubean_project_contracts`.
364
+ * Artifact producers declared by this adapter. Each entry is a
365
+ * per-contract renderer for a registered artifact kind (see
366
+ * `@glubean/sdk`'s `ArtifactKind` + `renderArtifact` / `KnownArtifacts`).
367
+ * Producers return the kind's Part type; cross-contract merging is the
368
+ * kind's responsibility.
369
+ *
370
+ * Keyed by `ArtifactKind.name`. Third-party plugins add new keys by
371
+ * augmenting `KnownArtifacts` / `KnownArtifactParts` / `KnownArtifactOptions`
372
+ * at the package root via `declare module "@glubean/sdk"`.
373
+ *
374
+ * Replaces the deprecated per-adapter `toMarkdown?` / `toOpenApi?` hooks
375
+ * (removed after v0.2.x) which polluted the generic interface with
376
+ * protocol-specific artifacts (OpenAPI is HTTP-only).
208
377
  */
209
- toMarkdown?: (projection: ExtractedContractProjection<SafeSchemas, SafeMeta>) => string;
378
+ artifacts?: {
379
+ [K in keyof KnownArtifacts]?: (projection: ExtractedContractProjection<SafeSchemas, SafeMeta>, options?: KnownArtifactOptions[K]) => KnownArtifactParts[K];
380
+ };
210
381
  /**
211
382
  * Optional: render the `target` string for display. HTTP: "POST /users"
212
383
  * stays as-is. gRPC: "Greeter/SayHello" might become "Greeter.SayHello()".
@@ -222,16 +393,23 @@ export interface ContractProtocolAdapter<Spec = unknown, RuntimeSchemas = unknow
222
393
  * Optional: execute a single case as a flow step.
223
394
  *
224
395
  * Core has already:
225
- * 1. Computed `resolvedInputs` via `step.bindings.in(state)` (may be partial)
396
+ * 1. Computed `resolvedInputs` via `step.bindings.in(state)`
226
397
  * 2. Prepared current flow state
227
- * 3. Passed the live contract instance (access merged scoped-factory state
398
+ * 3. **v10 (for migrated protocols)**: validated `resolvedInputs` against
399
+ * the case's `needs` schema via `runFlow` → `validateNeedsOutput`, so
400
+ * the adapter receives already-validated logical input.
401
+ * 4. Passed the live contract instance (access merged scoped-factory state
228
402
  * via `contract._spec`)
229
403
  *
230
- * Adapter responsibilities:
231
- * 1. Deep-merge `resolvedInputs` into the case's static input fields
232
- * 2. Run case setup / request / expect / verify / case teardown
233
- * (Rule 1: case teardown is step-local finally — see contract-flow §7.3)
234
- * 3. Return adapter-specific CaseOutput shape (HTTP: { status, headers, body })
404
+ * Adapter responsibility (post-Spike-4; uniform across HTTP / gRPC /
405
+ * GraphQL): treat `resolvedInputs` as the case's **logical input**
406
+ * matching `needs`. Call function-valued action fields (HTTP:
407
+ * `body`/`params`/`query`/`headers`; gRPC: `request`/`metadata`;
408
+ * GraphQL: `variables`/`headers`) with it. The contract case has no
409
+ * lifecycle in v10 — setup-style work belongs to a
410
+ * `contract.bootstrap()` overlay, NOT to the case itself. Return an
411
+ * adapter-specific CaseOutput (HTTP: `{ status, headers, body }`;
412
+ * gRPC: `GrpcCaseResult`; GraphQL: `GraphqlCaseResult`).
235
413
  *
236
414
  * Not implemented = this protocol cannot be referenced in a flow.
237
415
  */
@@ -242,11 +420,21 @@ export interface ContractProtocolAdapter<Spec = unknown, RuntimeSchemas = unknow
242
420
  resolvedInputs: unknown;
243
421
  }) => Promise<unknown>;
244
422
  /**
245
- * Optional: validate that a case can be referenced in a flow. Called by
246
- * ProtocolContract.case(key). HTTP's implementation rejects cases with
247
- * function-valued input fields (body/params/query/headers) because those
248
- * depend on case-local setup state unavailable in flow mode. See
249
- * contract-flow v9 §5.1.1 for rationale.
423
+ * Optional: validate that a case can be referenced in a flow.
424
+ *
425
+ * v10 call-site: `FlowBuilder.step(ref, bindings)` fires at
426
+ * step-declaration time, NOT at `ProtocolContract.case(key)` time.
427
+ * Case-ref creation is pure in v10 (attachment model §4.1);
428
+ * flow-safety is a step-declaration concern.
429
+ *
430
+ * Post-Spike-4 reality: NO built-in adapter implements this hook
431
+ * anymore. The v9 rule "function-valued action fields can't resolve
432
+ * in flow" is semantically reversed in v10 — function fields ARE the
433
+ * canonical flow input channel, receiving `resolvedInputs` via
434
+ * logical input. The hook is kept on the interface for protocol-
435
+ * adapter authors who have legitimate per-protocol flow constraints
436
+ * (e.g. streaming-only methods rejected from non-streaming flows in
437
+ * a future plugin).
250
438
  *
251
439
  * Throws on invalid case; returns undefined on success.
252
440
  */
@@ -270,13 +458,26 @@ export interface PayloadDescriptor {
270
458
  * @template PayloadSchemas Runtime (live) payload shape.
271
459
  * @template Meta Runtime free-form meta.
272
460
  */
273
- export interface ProtocolContract<Spec = unknown, PayloadSchemas = unknown, Meta = unknown> extends Array<Test> {
461
+ export interface ProtocolContract<Spec = unknown, PayloadSchemas = unknown, Meta = unknown, Cases extends Record<string, unknown> = Record<string, unknown>> extends Array<Test> {
274
462
  /**
275
463
  * Runtime projection with `id` injected by core. Consumers duck-type this.
276
464
  */
277
465
  readonly _projection: ContractProjection<PayloadSchemas, Meta> & {
278
466
  id: string;
279
467
  };
468
+ /**
469
+ * JSON-safe extracted projection — result of `adapter.normalize(_projection)`,
470
+ * computed by the dispatcher at contract construction. Scanner / MCP / CLI
471
+ * / cloud read this field directly as the canonical safe form. Never
472
+ * contains live refs (Zod schemas converted to plain JSON Schema etc.).
473
+ *
474
+ * Typed with the same generic slot as `_projection` for structural
475
+ * compatibility; at runtime it is always the Safe shape produced by
476
+ * the adapter's `normalize`.
477
+ */
478
+ readonly _extracted: ExtractedContractProjection<PayloadSchemas, Meta> & {
479
+ id: string;
480
+ };
280
481
  /**
281
482
  * Adapter-private runtime spec carrier. Holds the merged executable spec
282
483
  * (scoped-factory defaults + contract spec) used by `executeCaseInFlow`
@@ -294,7 +495,7 @@ export interface ProtocolContract<Spec = unknown, PayloadSchemas = unknown, Meta
294
495
  * headers as functions). Function fields reference case-local setup state
295
496
  * which is not available in flow mode. See contract-flow §5.1.1.
296
497
  */
297
- case(key: string): ContractCaseRef<InferInputs<PayloadSchemas>, InferOutput<PayloadSchemas>>;
498
+ case<K extends keyof Cases & string>(key: K): ContractCaseRef<InferCaseInput<Cases[K]>, InferOutput<PayloadSchemas>>;
298
499
  }
299
500
  /**
300
501
  * Adapter-defined helper: extract the "case inputs" shape from PayloadSchemas.
@@ -308,6 +509,23 @@ export interface ProtocolContract<Spec = unknown, PayloadSchemas = unknown, Meta
308
509
  * direct typing of their own ContractCaseRef.
309
510
  */
310
511
  export type InferInputs<_PayloadSchemas> = unknown;
512
+ /**
513
+ * Extract per-case logical input type from a case spec's `needs` field.
514
+ *
515
+ * Works for any case spec that extends `BaseCaseSpec<Needs>` and declares
516
+ * `needs: SchemaLike<T>`. Returns `void` for cases without `needs`.
517
+ *
518
+ * Used by `ProtocolContract.case<K>()` to infer `ContractCaseRef<Needs, ...>`
519
+ * per-case, so `contract.bootstrap(ref, { run: ... })` can type-check the
520
+ * run return against the specific case's Needs.
521
+ *
522
+ * @see contract-attachment-model.md v1.3 §4.1 / §5.3
523
+ * @see Spike 0 Finding 2 — requires `any` (not `unknown`) in don't-care slot
524
+ * for contravariant positions.
525
+ */
526
+ export type InferCaseInput<C> = C extends {
527
+ needs?: SchemaLike<infer N>;
528
+ } ? unknown extends N ? void : N : void;
311
529
  /** Adapter-defined helper: extract the "case output" shape from PayloadSchemas. */
312
530
  export type InferOutput<_PayloadSchemas> = unknown;
313
531
  /**
@@ -468,12 +686,34 @@ export interface FlowBuilder<State = unknown> {
468
686
  * lens functions (select / repack only; no I/O, no method calls, no
469
687
  * branching). Lens purity is enforced at Proxy dry-run time during
470
688
  * projection extraction.
689
+ *
690
+ * Single signature with rest-parameter conditional tuple (Spike 0 Finding 3).
691
+ * Two-overload form (historically tried) has a subtle hole: overload 1
692
+ * (void-input, no `in`) excess-property-fails when `in` is passed → TS
693
+ * falls through to overload 2, which accepts because `() => X` is
694
+ * bivariant-assignable to `() => void`. Conditional tuple is a single
695
+ * signature so TS doesn't get a second chance:
696
+ * - void-input case → `bindings` optional; `in` not present in the
697
+ * allowed shape
698
+ * - typed-input case → `bindings.in` REQUIRED
699
+ *
700
+ * In v10, `in` returns LOGICAL case input (matches the case's `needs`),
701
+ * NOT an adapter patch. HTTP adapter's `executeCaseInFlow` calls
702
+ * function-valued body/headers/params/query with this logical input
703
+ * (same mechanism as standalone `executeStandaloneCase`).
471
704
  */
472
- step<CaseInputs, CaseOutput, NewState = State>(ref: ContractCaseRef<CaseInputs, CaseOutput>, bindings?: {
473
- in?: (state: State) => CaseInputs;
474
- out?: (state: State, response: CaseOutput) => NewState;
475
- name?: string;
476
- }): FlowBuilder<NewState>;
705
+ step<CaseInputs, CaseOutput, NewState = State>(ref: ContractCaseRef<CaseInputs, CaseOutput>, ...args: [CaseInputs] extends [void] ? [
706
+ bindings?: {
707
+ out?: (state: State, response: CaseOutput) => NewState;
708
+ name?: string;
709
+ }
710
+ ] : [
711
+ bindings: {
712
+ in: (state: State) => CaseInputs;
713
+ out?: (state: State, response: CaseOutput) => NewState;
714
+ name?: string;
715
+ }
716
+ ]): FlowBuilder<NewState>;
477
717
  /**
478
718
  * Add a pure synchronous data-transform step. Accepts any synchronous TS
479
719
  * expression (template literals, method calls, .map()). Projection records