@antasphere/chassis-contract 1.0.0 → 1.0.2

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.
@@ -1,4 +1,5 @@
1
1
  import { z } from 'zod';
2
+ import { BILLING_PLANS, billingPlanSchema, type BillingPlan } from '@antasphere/contract';
2
3
  import type { HeaderReader, Principal } from './seams.js';
3
4
 
4
5
  /**
@@ -15,241 +16,53 @@ import type { HeaderReader, Principal } from './seams.js';
15
16
  * read the same declarations without pulling the server.
16
17
  */
17
18
 
18
- /**
19
- * The plan tiers, a CLOSED enum the hub owns and this contract mirrors so a
20
- * tool cannot invent one (§8b). `free` is the default with no subscription;
21
- * `pro` is the paid plan. "Enterprise" is not a tier but a per-account
22
- * override the hub serves.
23
- */
24
- export const ENTITLEMENT_TIERS = ['free', 'pro'] as const;
25
- export type EntitlementTier = (typeof ENTITLEMENT_TIERS)[number];
26
- export const entitlementTierSchema = z.enum(ENTITLEMENT_TIERS);
27
- /** The hub's name for the same closed enum (`BILLING_PLANS` in `@antasphere/contract`). */
28
- export const BILLING_PLANS = ENTITLEMENT_TIERS;
19
+ // ── The hub's half: the messages the tool exchanges with the hub ──────────
20
+ //
21
+ // The hub owns these shapes and publishes them as `@antasphere/contract`
22
+ // (the hub's own contract package, on npm at the hub's version); this file
23
+ // re-exports them under the names the chassis has always used, so a tool
24
+ // reads exactly what the hub wrote and a change at the hub reaches every
25
+ // tool through one dependency bump (PRDCT-3325; before it, a hand copy checked
26
+ // against the hub's wire snapshot). The chassis's OWN half — the
27
+ // declaration layer below — stays here.
28
+ export {
29
+ BILLING_PLANS,
30
+ USAGE_CHECK_REASONS,
31
+ USAGE_EVENT_MAX_FUTURE_MS,
32
+ USAGE_EVENT_MAX_PAST_MS,
33
+ USAGE_EVENTS_BATCH_MAX,
34
+ USAGE_REJECT_REASONS,
35
+ USAGE_ROUTE_ERRORS,
36
+ USAGE_WRITE_SCOPE,
37
+ usageCheckRequestSchema,
38
+ usageCheckSchema,
39
+ usageEventOccurrenceIssue,
40
+ usageEventResultSchema,
41
+ usageEventSchema,
42
+ usageEventsBatchSchema,
43
+ usageIngestResultSchema,
44
+ usageRejectReasonSchema
45
+ } from '@antasphere/contract';
46
+ export type {
47
+ UsageCheck,
48
+ UsageCheckReason,
49
+ UsageCheckRequest,
50
+ UsageEventResult,
51
+ UsageEventsBatch,
52
+ UsageIngestResult,
53
+ UsageRejectReason,
54
+ UsageRouteError
55
+ } from '@antasphere/contract';
29
56
 
30
57
  /**
31
- * The one scope of the tool → hub machine channel (§6): a `client_credentials`
32
- * token on the registry client, reaching `/usage/*` and nothing else.
58
+ * The plan tiers, a CLOSED enum the hub owns (`BILLING_PLANS` in
59
+ * `@antasphere/contract`), under the chassis's own names (§8b): `free` is the
60
+ * default with no subscription; `pro` is the paid plan. "Enterprise" is not
61
+ * a tier but a per-account override the hub serves.
33
62
  */
34
- export const USAGE_WRITE_SCOPE = 'usage:write';
35
-
36
- /**
37
- * The error codes the three tool routes of the hub (`POST /usage/events`,
38
- * `GET /usage/entitlements`, `POST /usage/check`) answer with, and the status
39
- * each rides on: the hub's `USAGE_ROUTE_ERRORS` (PRDCT-2677).
40
- * `tool_credential_required`: the caller is not a registry tool's machine
41
- * credential. `unknown_account`: no organization holds the `accountRef` (the
42
- * check and the entitlements read; the ingest answers it per event instead).
43
- * `validation_error`: the body or the query does not parse. The chassis maps
44
- * the check's two (`check.ts`): a 404 `unknown_account` and a 400 are the
45
- * hub's judgement, allowed and logged, never an outage.
46
- */
47
- export const USAGE_ROUTE_ERRORS = {
48
- tool_credential_required: 401,
49
- unknown_account: 404,
50
- validation_error: 400
51
- } as const;
52
- export type UsageRouteError = keyof typeof USAGE_ROUTE_ERRORS;
53
-
54
- /**
55
- * The wire shape of one usage event as the hub ingests it: the hub's
56
- * `usageEventSchema` (`packages/contract/src/schemas/billing.ts` of the hub,
57
- * PRDCT-2625), copied here and checked against the hub's wire snapshot
58
- * (`wire.ts`, `pnpm --filter @antasphere/chassis-contract wire:check`, the
59
- * `hub-wire` CI job; PRDCT-2677), so the fake hub of the test kit refuses
60
- * exactly what the real hub refuses (PRDCT-2629). `userId` is the HUB user
61
- * (the SSO `sub`), never the tool's local id, and null when the actor is a
62
- * resource owner the tool could not name; `accountRef` is the hub
63
- * organization id (a uuid) the tool carries as its workspace's central
64
- * account id. `toolSlug` is accepted by the hub only when it equals the
65
- * calling token's registry slug — the chassis NEVER sends it: the token is
66
- * the only authority on the tool's name, the body never names the tool
67
- * (PRDCT-2629; `UsageEvent` in seams.ts has no such field).
68
- */
69
- export const usageEventSchema = z
70
- .object({
71
- id: z.string().regex(/^[0-9A-HJKMNP-TV-Z]{26}$/, 'a ULID'),
72
- actionKey: z.string().min(1).max(120).optional(),
73
- meter: z.string().min(1).max(120).optional(),
74
- quantity: z.number().int().min(0).max(Number.MAX_SAFE_INTEGER),
75
- unit: z.string().min(1).max(40),
76
- occurredAt: z.iso.datetime({ offset: true }),
77
- workspaceId: z.string().min(1).max(128),
78
- accountRef: z.uuid(),
79
- userId: z.string().min(1).max(128).nullable().optional(),
80
- via: z.enum(['session', 'api_key', 'oauth']),
81
- resourceType: z.string().min(1).max(80).nullable().optional(),
82
- resourceId: z.string().min(1).max(256).nullable().optional(),
83
- toolSlug: z.string().min(1).max(64).optional(),
84
- source: z.object({
85
- instanceId: z.string().min(1).max(128),
86
- edition: z.string().min(1).max(32),
87
- version: z.string().min(1).max(64)
88
- })
89
- })
90
- .refine((e) => e.actionKey !== undefined || e.meter !== undefined, {
91
- message: 'actionKey (or its legacy alias meter) is required',
92
- path: ['actionKey']
93
- });
94
-
95
- /** The batch cap of `POST /usage/events` (the hub's `USAGE_EVENTS_BATCH_MAX`): at most this many events per post. */
96
- export const USAGE_EVENTS_BATCH_MAX = 500;
97
-
98
- /**
99
- * The body of `POST /usage/events` as the hub parses it (its
100
- * `usageEventsBatchSchema`): one to `USAGE_EVENTS_BATCH_MAX` elements, each
101
- * judged on its own against `usageEventSchema` afterwards.
102
- */
103
- export const usageEventsBatchSchema = z.object({
104
- events: z.array(z.unknown()).min(1).max(USAGE_EVENTS_BATCH_MAX)
105
- });
106
- export type UsageEventsBatch = z.infer<typeof usageEventsBatchSchema>;
107
-
108
- /**
109
- * Why the hub did not accept an event (its `USAGE_REJECT_REASONS`, a closed
110
- * list): `unknown_account`, `unknown_user`, `tool_mismatch`, and
111
- * `invalid_event` (the element does not parse, its `occurredAt` falls outside
112
- * the window, or its price exceeds `Number.MAX_SAFE_INTEGER`; `details` names
113
- * the field).
114
- */
115
- export const USAGE_REJECT_REASONS = [
116
- 'unknown_account',
117
- 'unknown_user',
118
- 'tool_mismatch',
119
- 'invalid_event'
120
- ] as const;
121
- export const usageRejectReasonSchema = z.enum(USAGE_REJECT_REASONS);
122
- export type UsageRejectReason = z.infer<typeof usageRejectReasonSchema>;
123
-
124
- /**
125
- * One element's answer. Since phase 2 an `accepted` result carries the
126
- * `credits` the hub debited for it (0 when the action has no price).
127
- */
128
- export const usageEventResultSchema = z.object({
129
- id: z.string().nullable(),
130
- status: z.enum(['accepted', 'duplicate', 'rejected']),
131
- reason: usageRejectReasonSchema.optional(),
132
- details: z.unknown().optional(),
133
- credits: z.number().int().optional()
134
- });
135
- export type UsageEventResult = z.infer<typeof usageEventResultSchema>;
136
-
137
- /**
138
- * The hub's answer to `POST /usage/events`: one result per element, in the
139
- * batch's order, and the three counts (always sent).
140
- */
141
- export const usageIngestResultSchema = z.object({
142
- results: z.array(usageEventResultSchema),
143
- accepted: z.number().int(),
144
- duplicate: z.number().int(),
145
- rejected: z.number().int()
146
- });
147
- export type UsageIngestResult = z.infer<typeof usageIngestResultSchema>;
148
-
149
- // ── The hub's window on an event's date (PRDCT-2630 at the hub, PRDCT-2644 here) ──
150
-
151
- /**
152
- * The window an event's `occurredAt` must fall in, measured against the
153
- * moment the hub receives it: the hub's `USAGE_EVENT_MAX_PAST_MS` and
154
- * `USAGE_EVENT_MAX_FUTURE_MS` (`packages/contract/src/schemas/billing.ts`
155
- * of the hub), same names and values, checked against the hub's wire
156
- * snapshot (`wire.ts`, `wire:check`, the `hub-wire` CI job; PRDCT-2677). Backward, seven days:
157
- * the queue's retry budget is about eight and a half hours, so an outage of
158
- * a night is covered many times over, and a week also covers an operator
159
- * re-driving held jobs by hand. Forward, five minutes: the skew every JWT
160
- * verifier already tolerates; anything further is a clock that is wrong.
161
- * Outside the window the hub answers `rejected(invalid_event)` naming
162
- * `occurredAt` and never clamps, so the poster refuses BEFORE posting: an
163
- * event the hub would refuse on its date is held where it was made, never
164
- * counted as a rejection at the hub (PRDCT-2644).
165
- */
166
- export const USAGE_EVENT_MAX_PAST_MS = 7 * 24 * 60 * 60 * 1000;
167
- export const USAGE_EVENT_MAX_FUTURE_MS = 5 * 60 * 1000;
168
-
169
- /**
170
- * Why an event's `occurredAt` is refused against the receipt time, or null
171
- * when it falls inside the window (both bounds INCLUSIVE). The hub's
172
- * `usageEventOccurrenceIssue`, copied (the wire snapshot's occurrence table
173
- * checks it on the hub's offsets): the one comparison both
174
- * halves run, the hub at ingest against its own clock, the chassis before
175
- * posting against its best estimate of the receipt (its own clock), so the
176
- * two never disagree on the sign or the edge.
177
- */
178
- export function usageEventOccurrenceIssue(
179
- occurredAt: Date,
180
- receivedAt: Date
181
- ): { path: 'occurredAt'; message: string } | null {
182
- const delta = occurredAt.getTime() - receivedAt.getTime();
183
- if (delta < -USAGE_EVENT_MAX_PAST_MS) {
184
- return {
185
- path: 'occurredAt',
186
- message: `more than ${USAGE_EVENT_MAX_PAST_MS / 86_400_000} days before the hub received the event`
187
- };
188
- }
189
- if (delta > USAGE_EVENT_MAX_FUTURE_MS) {
190
- return {
191
- path: 'occurredAt',
192
- message: `more than ${USAGE_EVENT_MAX_FUTURE_MS / 60_000} minutes after the hub received the event`
193
- };
194
- }
195
- return null;
196
- }
197
-
198
- // ── POST /usage/check: the price and the balance before an action (§5, §7 step 3) ──
199
-
200
- /**
201
- * The request of `POST /usage/check` (the hub's `UsageCheckRequest`,
202
- * PRDCT-2663): the paying account, the action key and the quantity of THIS
203
- * request. `unit` is accepted and ignored by the hub, which prices by its
204
- * own row; it is sent so the answer's unit can be compared and a mismatch
205
- * logged.
206
- */
207
- export const usageCheckRequestSchema = z.object({
208
- accountRef: z.uuid(),
209
- actionKey: z.string().min(1).max(120),
210
- quantity: z.number().int().min(0).max(Number.MAX_SAFE_INTEGER),
211
- unit: z.string().min(1).max(40).optional()
212
- });
213
- export type UsageCheckRequest = z.infer<typeof usageCheckRequestSchema>;
214
-
215
- /**
216
- * The three reasons a check refuses (`null` when allowed), the hub's
217
- * `USAGE_CHECK_REASONS`: `account_suspended` (checked first, whatever the
218
- * price), `unpriceable` (the price of this quantity exceeds
219
- * `Number.MAX_SAFE_INTEGER`: the hub clamps `credits` to that bound, and the
220
- * ingest would reject the same event on its `quantity`) and
221
- * `insufficient_credits` (`balance < credits`). Each is a refusal, never an
222
- * outage (PRDCT-2677).
223
- */
224
- export const USAGE_CHECK_REASONS = ['insufficient_credits', 'account_suspended', 'unpriceable'] as const;
225
- export type UsageCheckReason = (typeof USAGE_CHECK_REASONS)[number];
226
-
227
- /**
228
- * The hub's answer to `POST /usage/check` (its `UsageCheck`, PRDCT-2663),
229
- * checked against the hub's wire snapshot (PRDCT-2677): advisory, no side effect. `credits` is the price of
230
- * this quantity from the price book row effective now (0 and `priced:
231
- * false` when the tool has no row for the action: views are never priced,
232
- * an unknown key is not a refusal); `balance` the account's; `allowed` is
233
- * `balance >= credits` unless the organization is suspended, which refuses
234
- * whatever the price. `topUpUrl` is always present: the hub's billing page
235
- * for that organization, what a `402 entitlement_denied` carries straight
236
- * off the answer. No lower bound on `quantity` or `credits`, as at the hub: a
237
- * copy stricter than the hub reads a valid answer as an outage.
238
- */
239
- export const usageCheckSchema = z.object({
240
- accountRef: z.uuid(),
241
- actionKey: z.string(),
242
- quantity: z.number().int(),
243
- allowed: z.boolean(),
244
- credits: z.number().int(),
245
- balance: z.number().int(),
246
- unit: z.string().nullable(),
247
- priced: z.boolean(),
248
- plan: entitlementTierSchema,
249
- reason: z.enum(USAGE_CHECK_REASONS).nullable(),
250
- topUpUrl: z.string()
251
- });
252
- export type UsageCheck = z.infer<typeof usageCheckSchema>;
63
+ export const ENTITLEMENT_TIERS = BILLING_PLANS;
64
+ export type EntitlementTier = BillingPlan;
65
+ export const entitlementTierSchema = billingPlanSchema;
253
66
 
254
67
  /** The wire code of a credit refusal (§7 step 4), and its `details`. */
255
68
  export const ENTITLEMENT_DENIED = 'entitlement_denied';
@@ -492,7 +305,7 @@ export type ToolEntitlements = z.infer<typeof toolEntitlementsSchema>;
492
305
 
493
306
  /**
494
307
  * The hub's answer to `GET /usage/entitlements?accountRef=` (§5): the hub's
495
- * `usageEntitlementsSchema` (PRDCT-2636), checked against the hub's wire
308
+ * `usageEntitlementsSchema` (PRDCT-2636), the hub's own shape in
496
309
  * snapshot (PRDCT-2677). The account's
497
310
  * plan, resolved from the tier's defaults and the account's overrides; in
498
311
  * phase 1 `limits` and `features` are empty and the tool's own declared
package/src/index.ts CHANGED
@@ -33,6 +33,5 @@ export * from './schemas/teams.js';
33
33
  export * from './schemas/demo-passes.js';
34
34
  export * from './seams.js';
35
35
  export * from './entitlements.js';
36
- export * from './wire.js';
37
36
  export * from './define.js';
38
37
  export type { ToolIdentity } from './identity.js';
package/dist/wire.d.ts DELETED
@@ -1,101 +0,0 @@
1
- import { z } from 'zod';
2
- /**
3
- * The chassis's side of the hub–tool wire check (PRDCT-2677). The hub owns
4
- * the messages the tools exchange with it and publishes them as ONE
5
- * generated snapshot, `packages/contract/wire/hub-tool-messages.json` of the
6
- * hub, built by its `packages/contract/src/wire.ts`. The block below, from
7
- * `WIRE_SCHEMA_KEYS` to `buildWireSnapshot`, is the chassis's copy of that
8
- * builder, kept VERBATIM so both sides compute the same picture: the same
9
- * JSON Schema export, the same probe verdicts, the same occurrence table.
10
- * The hub's inputs (its offsets and probe payloads) and its definitions are
11
- * NOT copied: the inputs are read back from the hub's file
12
- * (`wireInputsOf`), the definitions are this package's own copies
13
- * (`CHASSIS_WIRE_DEFINITIONS`, from `entitlements.ts`).
14
- *
15
- * `compareWireSnapshots` names every difference by its dotted path;
16
- * `scripts/hub-wire-check.mjs` (`pnpm --filter @antasphere/chassis-contract
17
- * wire:check`, the `hub-wire` CI job against the hub's `dev`) fails on any.
18
- * The check runs one way: the hub changes first, the chassis follows.
19
- */
20
- /** The keys of the six shapes, the same on both sides. */
21
- export declare const WIRE_SCHEMA_KEYS: readonly ["usageEvent", "usageEventsBatch", "usageIngestResult", "usageEntitlements", "usageCheckRequest", "usageCheck"];
22
- export type WireSchemaKey = (typeof WIRE_SCHEMA_KEYS)[number];
23
- export interface WireConstants {
24
- USAGE_WRITE_SCOPE: string;
25
- BILLING_PLANS: readonly string[];
26
- USAGE_EVENTS_BATCH_MAX: number;
27
- USAGE_EVENT_MAX_PAST_MS: number;
28
- USAGE_EVENT_MAX_FUTURE_MS: number;
29
- USAGE_CHECK_REASONS: readonly string[];
30
- USAGE_REJECT_REASONS: readonly string[];
31
- USAGE_ROUTE_ERRORS: Readonly<Record<string, number>>;
32
- }
33
- export interface WireProbe {
34
- name: string;
35
- input: unknown;
36
- }
37
- export interface WireProbeResult extends WireProbe {
38
- /** Whether the schema accepts the input. */
39
- ok: boolean;
40
- }
41
- export interface WireOccurrence {
42
- /** The event's `occurredAt` minus the receipt time, in milliseconds. */
43
- offsetMs: number;
44
- issue: {
45
- path: 'occurredAt';
46
- message: string;
47
- } | null;
48
- }
49
- /** What one side feeds the builder: its own definitions. */
50
- export interface WireDefinitions {
51
- constants: WireConstants;
52
- schemas: Record<WireSchemaKey, z.ZodType>;
53
- occurrenceIssue: (occurredAt: Date, receivedAt: Date) => {
54
- path: 'occurredAt';
55
- message: string;
56
- } | null;
57
- }
58
- /** The inputs the snapshot is computed on: the hub's, read back by the chassis from the hub's file. */
59
- export interface WireInputs {
60
- occurrenceOffsetsMs: readonly number[];
61
- probes: Record<WireSchemaKey, readonly WireProbe[]>;
62
- }
63
- export interface HubToolWireSnapshot {
64
- v: 1;
65
- constants: WireConstants;
66
- schemas: Record<WireSchemaKey, unknown>;
67
- occurrence: WireOccurrence[];
68
- probes: Record<WireSchemaKey, WireProbeResult[]>;
69
- }
70
- /**
71
- * Build the snapshot from one side's definitions on the given inputs. The
72
- * SAME function runs on both sides (the chassis carries a verbatim copy):
73
- * the hub with its own inputs, the chassis with the inputs read from the
74
- * hub's file. Deterministic: no clock, no randomness, no environment.
75
- */
76
- export declare function buildWireSnapshot(defs: WireDefinitions, inputs: WireInputs): HubToolWireSnapshot;
77
- /** The chassis's definitions: this package's copies of the hub's shapes, under the hub's keys. */
78
- export declare const CHASSIS_WIRE_DEFINITIONS: WireDefinitions;
79
- /** The inputs the hub computed its snapshot on, read back from its file: the offsets and the probe payloads. */
80
- export declare function wireInputsOf(reference: HubToolWireSnapshot): WireInputs;
81
- /** The snapshot the chassis's copies give on the hub's own inputs: what must equal the hub's file. */
82
- export declare function chassisWireSnapshot(reference: HubToolWireSnapshot): HubToolWireSnapshot;
83
- /** One place where the hub's snapshot and the chassis's differ: its dotted path and the two values. */
84
- export interface WireDifference {
85
- path: string;
86
- hub: unknown;
87
- chassis: unknown;
88
- }
89
- /**
90
- * Every difference between the hub's snapshot and the chassis's, by dotted
91
- * path (`constants.USAGE_CHECK_REASONS[2]`,
92
- * `schemas.usageCheck.properties.reason.anyOf[0].enum`,
93
- * `probes.usageCheck[3].ok`). Objects compare by the union of their keys,
94
- * order ignored, an absent key and `undefined` being the same; arrays by
95
- * index, a length difference being one difference at the array's path.
96
- * Deterministic: keys sorted, arrays in order. Empty when they agree.
97
- */
98
- export declare function compareWireSnapshots(hub: HubToolWireSnapshot, chassis: HubToolWireSnapshot): WireDifference[];
99
- /** One line of figures for a snapshot: `6 shapes, N constants, M probes, K occurrence offsets`. */
100
- export declare function describeWireSnapshot(snapshot: HubToolWireSnapshot): string;
101
- //# sourceMappingURL=wire.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"wire.d.ts","sourceRoot":"","sources":["../src/wire.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAmBxB;;;;;;;;;;;;;;;;;GAiBG;AAIH,0DAA0D;AAC1D,eAAO,MAAM,gBAAgB,0HAOnB,CAAC;AACX,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE9D,MAAM,WAAW,aAAa;IAC5B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,sBAAsB,EAAE,MAAM,CAAC;IAC/B,uBAAuB,EAAE,MAAM,CAAC;IAChC,yBAAyB,EAAE,MAAM,CAAC;IAClC,mBAAmB,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,oBAAoB,EAAE,SAAS,MAAM,EAAE,CAAC;IACxC,kBAAkB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACtD;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,eAAgB,SAAQ,SAAS;IAChD,4CAA4C;IAC5C,EAAE,EAAE,OAAO,CAAC;CACb;AAED,MAAM,WAAW,cAAc;IAC7B,wEAAwE;IACxE,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE;QAAE,IAAI,EAAE,YAAY,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CACvD;AAED,4DAA4D;AAC5D,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,aAAa,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC,aAAa,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC;IAC1C,eAAe,EAAE,CAAC,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,KAAK;QAAE,IAAI,EAAE,YAAY,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CACzG;AAED,uGAAuG;AACvG,MAAM,WAAW,UAAU;IACzB,mBAAmB,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,MAAM,EAAE,MAAM,CAAC,aAAa,EAAE,SAAS,SAAS,EAAE,CAAC,CAAC;CACrD;AAED,MAAM,WAAW,mBAAmB;IAClC,CAAC,EAAE,CAAC,CAAC;IACL,SAAS,EAAE,aAAa,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;IACxC,UAAU,EAAE,cAAc,EAAE,CAAC;IAC7B,MAAM,EAAE,MAAM,CAAC,aAAa,EAAE,eAAe,EAAE,CAAC,CAAC;CAClD;AAKD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,eAAe,EAAE,MAAM,EAAE,UAAU,GAAG,mBAAmB,CAiChG;AAID,kGAAkG;AAClG,eAAO,MAAM,wBAAwB,EAAE,eAoBtC,CAAC;AAEF,gHAAgH;AAChH,wBAAgB,YAAY,CAAC,SAAS,EAAE,mBAAmB,GAAG,UAAU,CASvE;AAED,sGAAsG;AACtG,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,mBAAmB,GAAG,mBAAmB,CAEvF;AAED,uGAAuG;AACvG,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,OAAO,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;CAClB;AA+BD;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,mBAAmB,EACxB,OAAO,EAAE,mBAAmB,GAC3B,cAAc,EAAE,CAIlB;AAED,mGAAmG;AACnG,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,mBAAmB,GAAG,MAAM,CAK1E"}
package/dist/wire.js DELETED
@@ -1,161 +0,0 @@
1
- import { z } from 'zod';
2
- import { BILLING_PLANS, USAGE_CHECK_REASONS, USAGE_EVENT_MAX_FUTURE_MS, USAGE_EVENT_MAX_PAST_MS, USAGE_EVENTS_BATCH_MAX, USAGE_REJECT_REASONS, USAGE_ROUTE_ERRORS, USAGE_WRITE_SCOPE, entitlementProfileSchema, usageCheckRequestSchema, usageCheckSchema, usageEventOccurrenceIssue, usageEventSchema, usageEventsBatchSchema, usageIngestResultSchema } from './entitlements.js';
3
- /**
4
- * The chassis's side of the hub–tool wire check (PRDCT-2677). The hub owns
5
- * the messages the tools exchange with it and publishes them as ONE
6
- * generated snapshot, `packages/contract/wire/hub-tool-messages.json` of the
7
- * hub, built by its `packages/contract/src/wire.ts`. The block below, from
8
- * `WIRE_SCHEMA_KEYS` to `buildWireSnapshot`, is the chassis's copy of that
9
- * builder, kept VERBATIM so both sides compute the same picture: the same
10
- * JSON Schema export, the same probe verdicts, the same occurrence table.
11
- * The hub's inputs (its offsets and probe payloads) and its definitions are
12
- * NOT copied: the inputs are read back from the hub's file
13
- * (`wireInputsOf`), the definitions are this package's own copies
14
- * (`CHASSIS_WIRE_DEFINITIONS`, from `entitlements.ts`).
15
- *
16
- * `compareWireSnapshots` names every difference by its dotted path;
17
- * `scripts/hub-wire-check.mjs` (`pnpm --filter @antasphere/chassis-contract
18
- * wire:check`, the `hub-wire` CI job against the hub's `dev`) fails on any.
19
- * The check runs one way: the hub changes first, the chassis follows.
20
- */
21
- // ── Copied VERBATIM from the hub's packages/contract/src/wire.ts ──────────
22
- /** The keys of the six shapes, the same on both sides. */
23
- export const WIRE_SCHEMA_KEYS = [
24
- 'usageEvent',
25
- 'usageEventsBatch',
26
- 'usageIngestResult',
27
- 'usageEntitlements',
28
- 'usageCheckRequest',
29
- 'usageCheck'
30
- ];
31
- /** A fixed receipt time, so the occurrence table is the same on every run. */
32
- const RECEIVED_AT = new Date('2026-09-23T12:00:00.000Z');
33
- /**
34
- * Build the snapshot from one side's definitions on the given inputs. The
35
- * SAME function runs on both sides (the chassis carries a verbatim copy):
36
- * the hub with its own inputs, the chassis with the inputs read from the
37
- * hub's file. Deterministic: no clock, no randomness, no environment.
38
- */
39
- export function buildWireSnapshot(defs, inputs) {
40
- const schemas = {};
41
- const probes = {};
42
- for (const key of WIRE_SCHEMA_KEYS) {
43
- const schema = defs.schemas[key];
44
- // A refinement has no JSON Schema form and is dropped on both sides
45
- // alike; the probes below carry what it decides.
46
- schemas[key] = z.toJSONSchema(schema, { unrepresentable: 'any' });
47
- probes[key] = inputs.probes[key].map((probe) => ({
48
- name: probe.name,
49
- input: probe.input,
50
- ok: schema.safeParse(probe.input).success
51
- }));
52
- }
53
- return {
54
- v: 1,
55
- constants: {
56
- USAGE_WRITE_SCOPE: defs.constants.USAGE_WRITE_SCOPE,
57
- BILLING_PLANS: [...defs.constants.BILLING_PLANS],
58
- USAGE_EVENTS_BATCH_MAX: defs.constants.USAGE_EVENTS_BATCH_MAX,
59
- USAGE_EVENT_MAX_PAST_MS: defs.constants.USAGE_EVENT_MAX_PAST_MS,
60
- USAGE_EVENT_MAX_FUTURE_MS: defs.constants.USAGE_EVENT_MAX_FUTURE_MS,
61
- USAGE_CHECK_REASONS: [...defs.constants.USAGE_CHECK_REASONS],
62
- USAGE_REJECT_REASONS: [...defs.constants.USAGE_REJECT_REASONS],
63
- USAGE_ROUTE_ERRORS: { ...defs.constants.USAGE_ROUTE_ERRORS }
64
- },
65
- schemas,
66
- occurrence: inputs.occurrenceOffsetsMs.map((offsetMs) => ({
67
- offsetMs,
68
- issue: defs.occurrenceIssue(new Date(RECEIVED_AT.getTime() + offsetMs), RECEIVED_AT)
69
- })),
70
- probes
71
- };
72
- }
73
- // ── The chassis's own half ─────────────────────────────────────────────────
74
- /** The chassis's definitions: this package's copies of the hub's shapes, under the hub's keys. */
75
- export const CHASSIS_WIRE_DEFINITIONS = {
76
- constants: {
77
- USAGE_WRITE_SCOPE,
78
- BILLING_PLANS,
79
- USAGE_EVENTS_BATCH_MAX,
80
- USAGE_EVENT_MAX_PAST_MS,
81
- USAGE_EVENT_MAX_FUTURE_MS,
82
- USAGE_CHECK_REASONS,
83
- USAGE_REJECT_REASONS,
84
- USAGE_ROUTE_ERRORS
85
- },
86
- schemas: {
87
- usageEvent: usageEventSchema,
88
- usageEventsBatch: usageEventsBatchSchema,
89
- usageIngestResult: usageIngestResultSchema,
90
- usageEntitlements: entitlementProfileSchema,
91
- usageCheckRequest: usageCheckRequestSchema,
92
- usageCheck: usageCheckSchema
93
- },
94
- occurrenceIssue: usageEventOccurrenceIssue
95
- };
96
- /** The inputs the hub computed its snapshot on, read back from its file: the offsets and the probe payloads. */
97
- export function wireInputsOf(reference) {
98
- const probes = {};
99
- for (const key of WIRE_SCHEMA_KEYS) {
100
- probes[key] = (reference.probes[key] ?? []).map((probe) => ({ name: probe.name, input: probe.input }));
101
- }
102
- return {
103
- occurrenceOffsetsMs: reference.occurrence.map((row) => row.offsetMs),
104
- probes
105
- };
106
- }
107
- /** The snapshot the chassis's copies give on the hub's own inputs: what must equal the hub's file. */
108
- export function chassisWireSnapshot(reference) {
109
- return buildWireSnapshot(CHASSIS_WIRE_DEFINITIONS, wireInputsOf(reference));
110
- }
111
- function isPlainObject(value) {
112
- return typeof value === 'object' && value !== null && !Array.isArray(value);
113
- }
114
- function childPath(parent, key) {
115
- return /^[A-Za-z_$][\w$]*$/.test(key)
116
- ? parent === ''
117
- ? key
118
- : `${parent}.${key}`
119
- : `${parent}[${JSON.stringify(key)}]`;
120
- }
121
- function compareAt(path, hub, chassis, out) {
122
- if (Array.isArray(hub) && Array.isArray(chassis)) {
123
- if (hub.length !== chassis.length) {
124
- out.push({ path, hub, chassis });
125
- return;
126
- }
127
- for (let i = 0; i < hub.length; i += 1)
128
- compareAt(`${path}[${i}]`, hub[i], chassis[i], out);
129
- return;
130
- }
131
- if (isPlainObject(hub) && isPlainObject(chassis)) {
132
- const keys = [...new Set([...Object.keys(hub), ...Object.keys(chassis)])].sort();
133
- for (const key of keys)
134
- compareAt(childPath(path, key), hub[key], chassis[key], out);
135
- return;
136
- }
137
- if (!Object.is(hub, chassis))
138
- out.push({ path, hub, chassis });
139
- }
140
- /**
141
- * Every difference between the hub's snapshot and the chassis's, by dotted
142
- * path (`constants.USAGE_CHECK_REASONS[2]`,
143
- * `schemas.usageCheck.properties.reason.anyOf[0].enum`,
144
- * `probes.usageCheck[3].ok`). Objects compare by the union of their keys,
145
- * order ignored, an absent key and `undefined` being the same; arrays by
146
- * index, a length difference being one difference at the array's path.
147
- * Deterministic: keys sorted, arrays in order. Empty when they agree.
148
- */
149
- export function compareWireSnapshots(hub, chassis) {
150
- const out = [];
151
- compareAt('', hub, chassis, out);
152
- return out;
153
- }
154
- /** One line of figures for a snapshot: `6 shapes, N constants, M probes, K occurrence offsets`. */
155
- export function describeWireSnapshot(snapshot) {
156
- const shapes = Object.keys(snapshot.schemas).length;
157
- const constants = Object.keys(snapshot.constants).length;
158
- const probes = Object.values(snapshot.probes).reduce((n, list) => n + list.length, 0);
159
- return `${shapes} shapes, ${constants} constants, ${probes} probes, ${snapshot.occurrence.length} occurrence offsets`;
160
- }
161
- //# sourceMappingURL=wire.js.map
package/dist/wire.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"wire.js","sourceRoot":"","sources":["../src/wire.ts"],"names":[],"mappings":"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"}