@amboras-dev/capability-kit 0.2.1 → 0.3.0

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.
package/README.md CHANGED
@@ -6,8 +6,9 @@ merchant action: id, zod input/output, policy and agent text. The kit checks it
6
6
  once, converts money at one boundary, answers errors in one shape and emits a
7
7
  hashed manifest the other repo re-checks on load. CommonJS + ESM + types; Node >= 20 and
8
8
  browsers. One runtime dependency, `@amboras-dev/money` (the storage rule, conversion
9
- and money view; the kit pins its exact version), and the `zod` peer (`^3.25.76 || ^4.0.0`,
10
- imported only as `zod/v4`; zod 3.25.0 ships without `dist/` and cannot load `zod/v4`).
9
+ and money view; the kit pins its exact version), and the `zod` peer (`^3.25.76 || ^4.6.6`,
10
+ imported only as `zod/v4`; zod 3.25.0 ships without `dist/` and cannot load `zod/v4`;
11
+ the 4.x floor is 4.6.6, the first release patched for GHSA-mrhx-c7xc-m3w5, which has no 3.x fix).
11
12
 
12
13
  ```ts
13
14
  import { defineCapability, money, toStorageAmount, moneyView, emitManifest, parseManifest } from '@amboras-dev/capability-kit'
@@ -136,8 +137,8 @@ count, or a count that is not a non-negative integer.
136
137
  loose objects, so a field added by a newer kit passes through and stays covered
137
138
  by the hash. The hash proves integrity, not origin: trust comes from reading the
138
139
  committed file.
139
- - **zod 3.25 and 4.x.** The suite runs three times: on zod 4.3.6, on zod 4.0.0
140
- (`vitest.zod40.config.ts`) and on zod 3.25.76's `zod/v4`
140
+ - **zod 3.25 and 4.x.** The suite runs three times: on zod 4.6.7, on zod 4.6.6
141
+ (`vitest.zod46.config.ts`, the 4.x floor) and on zod 3.25.76's `zod/v4`
141
142
  (`vitest.zod3.config.ts`); types are checked against all three. A manifest
142
143
  emitted on 3.25 (`test-fixtures/manifest.zod-3.25.json`) parses on every line,
143
144
  and each line's hash is pinned. zod 3.25's
@@ -152,8 +153,8 @@ count, or a count that is not a non-negative integer.
152
153
  ## Testing
153
154
 
154
155
  ```bash
155
- pnpm test # vitest + 100% coverage on zod 4.3.6, then the same suite on 3.25.76 and 4.0.0
156
- pnpm typecheck # src (no Node types), tests, and src+tests against zod 3.25 and 4.0 types
156
+ pnpm test # vitest + 100% coverage on zod 4.6.7, then the same suite on 3.25.76 and 4.6.6
157
+ pnpm typecheck # src (no Node types), tests, and src+tests against zod 3.25 and 4.6.6 types
157
158
  # regenerate the 3.25 manifest fixture after a deliberate change:
158
159
  UPDATE_FIXTURES=1 npx vitest run --config vitest.zod3.config.ts src/manifest-cross-zod.test.ts
159
160
  ```
package/dist/index.cjs CHANGED
@@ -2,7 +2,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  let zod_v4 = require("zod/v4");
3
3
  let _amboras_dev_money = require("@amboras-dev/money");
4
4
  let _amboras_dev_money_ai = require("@amboras-dev/money/ai");
5
- //#region src/canonical-json.ts
5
+ // src/canonical-json.ts
6
6
  function serialize(value, seen) {
7
7
  if (value !== null && typeof value === "object" && typeof value.toJSON === "function") value = value.toJSON();
8
8
  if (value === null) return "null";
@@ -35,8 +35,7 @@ function serialize(value, seen) {
35
35
  function canonicalJson(v) {
36
36
  return serialize(v, /* @__PURE__ */ new Set()) ?? "null";
37
37
  }
38
- //#endregion
39
- //#region src/errors.ts
38
+ // src/errors.ts
40
39
  const STATUS = {
41
40
  invalid_input: 400,
42
41
  forbidden: 403,
@@ -165,8 +164,7 @@ function fromZodError(err, options = {}) {
165
164
  issues
166
165
  });
167
166
  }
168
- //#endregion
169
- //#region src/ids.ts
167
+ // src/ids.ts
170
168
  const AREAS = [
171
169
  "promotions",
172
170
  "catalog",
@@ -197,8 +195,7 @@ function areaOf(id) {
197
195
  function isRole(value) {
198
196
  return value === "owner" || value === "manager" || value === "staff";
199
197
  }
200
- //#endregion
201
- //#region src/money.ts
198
+ // src/money.ts
202
199
  /**
203
200
  * A bad amount or currency code. It is an `invalid_input` CapabilityError, so an
204
201
  * adapter that maps CapabilityError answers 400 with the rule (and the field,
@@ -354,8 +351,7 @@ function moneyView(minor, currency) {
354
351
  throw toCapabilityMoneyError(error);
355
352
  }
356
353
  }
357
- //#endregion
358
- //#region src/json-schema.ts
354
+ // src/json-schema.ts
359
355
  /**
360
356
  * The exact conversion every manifest uses. Throws for types JSON Schema cannot
361
357
  * express. Every money() field gets its marker back, and its unit sentence when
@@ -433,8 +429,7 @@ function omitFields(schema, fields) {
433
429
  }
434
430
  return copy;
435
431
  }
436
- //#endregion
437
- //#region src/guards.ts
432
+ // src/guards.ts
438
433
  /**
439
434
  * Tenant and actor ids come from the call context, never from input. A name is
440
435
  * refused when, lower-cased with separators removed, it ends in one of these
@@ -587,8 +582,7 @@ function checkEntry(entry) {
587
582
  if (typeof entry.agent.description !== "string" || entry.agent.description.trim() === "") fail(id, "agent.description is required");
588
583
  if (entry.agent.toolName !== void 0 && !TOOL_NAME.test(entry.agent.toolName)) fail(id, `agent.toolName must match ${TOOL_NAME}`);
589
584
  }
590
- //#endregion
591
- //#region src/define.ts
585
+ // src/define.ts
592
586
  function convert(schema, io, id) {
593
587
  try {
594
588
  return toJsonSchema(schema, io);
@@ -638,8 +632,7 @@ function defineCapability(def) {
638
632
  agent: freezeCopy(def.agent)
639
633
  });
640
634
  }
641
- //#endregion
642
- //#region src/sha256.ts
635
+ // src/sha256.ts
643
636
  const K = new Uint32Array([
644
637
  1116352408,
645
638
  1899447441,
@@ -782,8 +775,7 @@ function sha256Hex(text) {
782
775
  for (const word of h) hex += word.toString(16).padStart(8, "0");
783
776
  return hex;
784
777
  }
785
- //#endregion
786
- //#region src/idempotency.ts
778
+ // src/idempotency.ts
787
779
  /**
788
780
  * 8–100 of `A-Z a-z 0-9 . _ : -`. The underscore is there because the
789
781
  * orchestrator's key is `cap.{runId}.{toolCallId}` and model tool call ids
@@ -801,8 +793,7 @@ function requestFingerprint(id, input) {
801
793
  input
802
794
  }));
803
795
  }
804
- //#endregion
805
- //#region src/manifest.ts
796
+ // src/manifest.ts
806
797
  const hashOf = (capabilities) => sha256Hex(canonicalJson(capabilities));
807
798
  /** Plain JSON with keys sorted at every level, so the committed file is stable text. */
808
799
  const sortedJson = (value) => JSON.parse(canonicalJson(value));
@@ -926,8 +917,7 @@ function parseManifest(json) {
926
917
  if (actual !== manifest.hash) throw new CapabilityManifestError(`Capability manifest hash mismatch: header ${manifest.hash}, content ${actual}`);
927
918
  return manifest;
928
919
  }
929
- //#endregion
930
- //#region src/policy.ts
920
+ // src/policy.ts
931
921
  function roleCheck(policy, ctx) {
932
922
  const { actor } = ctx;
933
923
  if (actor.kind === "internal") return null;
@@ -1014,14 +1004,23 @@ function confirmationRequired(policy, records) {
1014
1004
  if (typeof records !== "number" || !Number.isInteger(records) || records < 0) return true;
1015
1005
  return records >= confirm.when.recordsAtLeast;
1016
1006
  }
1017
- //#endregion
1018
1007
  exports.AREAS = AREAS;
1019
1008
  exports.CapabilityDefinitionError = CapabilityDefinitionError;
1020
1009
  exports.CapabilityError = CapabilityError;
1021
1010
  exports.CapabilityManifestError = CapabilityManifestError;
1022
1011
  exports.IDEMPOTENCY_KEY_PATTERN = IDEMPOTENCY_KEY_PATTERN;
1023
- exports.MONEY_META_KEY = _amboras_dev_money_ai.MONEY_META_KEY;
1024
- exports.MONEY_UNIT_SENTENCE = _amboras_dev_money_ai.MONEY_UNIT_SENTENCE;
1012
+ Object.defineProperty(exports, "MONEY_META_KEY", {
1013
+ enumerable: true,
1014
+ get: function() {
1015
+ return _amboras_dev_money_ai.MONEY_META_KEY;
1016
+ }
1017
+ });
1018
+ Object.defineProperty(exports, "MONEY_UNIT_SENTENCE", {
1019
+ enumerable: true,
1020
+ get: function() {
1021
+ return _amboras_dev_money_ai.MONEY_UNIT_SENTENCE;
1022
+ }
1023
+ });
1025
1024
  exports.MoneyError = MoneyError;
1026
1025
  exports.ROLE_RANK = ROLE_RANK;
1027
1026
  exports.areaOf = areaOf;
package/dist/index.d.cts CHANGED
@@ -1,10 +1,7 @@
1
1
  import { z } from "zod/v4";
2
2
  import { MONEY_META_KEY, MONEY_UNIT_SENTENCE } from "@amboras-dev/money/ai";
3
- //#region src/canonical-json.d.ts
4
3
  /** Sorted keys, no whitespace. Throws on BigInt and circular values; `undefined` at the top serializes as `null`. */
5
4
  export declare function canonicalJson(v: unknown): string;
6
- //#endregion
7
- //#region src/ids.d.ts
8
5
  export declare const AREAS: readonly ["promotions", "catalog", "inventory", "setup", "content", "orders", "payments", "domains", "publish"];
9
6
  type Area = (typeof AREAS)[number];
10
7
  /** `<area>.<verb>` or `<area>.<entity>.<verb>`: lowercase segments of `a-z` and `_`. */
@@ -16,8 +13,6 @@ export declare const ROLE_RANK: Readonly<Record<Role, number>>;
16
13
  export declare function isCapabilityId(value: unknown): value is CapabilityId;
17
14
  /** The area an id belongs to (`promotions.create` → `promotions`). */
18
15
  export declare function areaOf(id: CapabilityId): Area;
19
- //#endregion
20
- //#region src/context.d.ts
21
16
  type Actor = {
22
17
  kind: 'member';
23
18
  profileId: string;
@@ -34,8 +29,6 @@ interface CapabilityCallContext {
34
29
  surface: Surface;
35
30
  runId?: string;
36
31
  }
37
- //#endregion
38
- //#region src/json-schema.d.ts
39
32
  type JsonSchema = {
40
33
  [key: string]: unknown;
41
34
  };
@@ -44,8 +37,6 @@ type JsonSchema = {
44
37
  * dropped from `required`. Adapters build the model-facing input with this.
45
38
  */
46
39
  export declare function omitFields(schema: JsonSchema, fields: readonly string[]): JsonSchema;
47
- //#endregion
48
- //#region src/policy-types.d.ts
49
40
  interface CapabilityPolicy {
50
41
  minRole: Role;
51
42
  planFeature?: string;
@@ -63,8 +54,6 @@ interface CapabilityPolicy {
63
54
  perMinute: number;
64
55
  };
65
56
  }
66
- //#endregion
67
- //#region src/define.d.ts
68
57
  interface CapabilityAgentSpec {
69
58
  /** What it does and when to use it, written for the model. */
70
59
  description: string;
@@ -107,8 +96,6 @@ interface CapabilityDefinition<I = unknown, O = unknown, Ctx = unknown> {
107
96
  * minRole, confirm threshold, rate limit or toolName.
108
97
  */
109
98
  export declare function defineCapability<I, O, Ctx = unknown>(def: CapabilityDefinition<I, O, Ctx>): Readonly<CapabilityDefinition<I, O, Ctx>>;
110
- //#endregion
111
- //#region src/errors.d.ts
112
99
  type CapabilityErrorCode = 'invalid_input' | 'forbidden' | 'not_found' | 'conflict' | 'confirmation_required' | 'rate_limited' | 'idempotency_conflict' | 'unavailable' | 'internal';
113
100
  interface CapabilityErrorBody {
114
101
  code: CapabilityErrorCode;
@@ -158,8 +145,6 @@ interface FromZodErrorOptions {
158
145
  * `options.renamed` for steering removed field names.
159
146
  */
160
147
  export declare function fromZodError(err: z.ZodError, options?: FromZodErrorOptions): CapabilityError;
161
- //#endregion
162
- //#region src/idempotency.d.ts
163
148
  /**
164
149
  * 8–100 of `A-Z a-z 0-9 . _ : -`. The underscore is there because the
165
150
  * orchestrator's key is `cap.{runId}.{toolCallId}` and model tool call ids
@@ -170,8 +155,6 @@ export declare const IDEMPOTENCY_KEY_PATTERN: RegExp;
170
155
  export declare function requiresIdempotencyKey(policy: Pick<CapabilityPolicy, 'effect' | 'idempotent'>): boolean;
171
156
  /** sha256 hex of canonicalJson({ id, input }): same key + different fingerprint = a different request. */
172
157
  export declare function requestFingerprint(id: CapabilityId, input: unknown): string;
173
- //#endregion
174
- //#region src/manifest.d.ts
175
158
  interface ManifestEntry {
176
159
  id: CapabilityId;
177
160
  version: number;
@@ -209,8 +192,6 @@ export declare function emitManifest(defs: readonly AnyCapabilityDefinition[], s
209
192
  * the file is read (the committed copy), not from the hash.
210
193
  */
211
194
  export declare function parseManifest(json: unknown): CapabilityManifest;
212
- //#endregion
213
- //#region src/money.d.ts
214
195
  /**
215
196
  * A bad amount or currency code. It is an `invalid_input` CapabilityError, so an
216
197
  * adapter that maps CapabilityError answers 400 with the rule (and the field,
@@ -286,8 +267,6 @@ export declare const moneyViewSchema: z.ZodType<MoneyView>;
286
267
  * unknown code throws `currency_invalid`.
287
268
  */
288
269
  export declare function moneyView(minor: number, currency: string): MoneyView;
289
- //#endregion
290
- //#region src/policy.d.ts
291
270
  /** Phase 1 adapters pass observe/observe. */
292
271
  interface PolicyEnforcement {
293
272
  role: 'enforce' | 'observe';
@@ -310,5 +289,4 @@ export declare function evaluatePolicy(policy: CapabilityPolicy, ctx: Capability
310
289
  * is not a non-negative integer, requires confirmation (the adapter could not count).
311
290
  */
312
291
  export declare function confirmationRequired(policy: Pick<CapabilityPolicy, 'confirm'>, records?: number): boolean;
313
- //#endregion
314
292
  export { type Actor, type AnyCapabilityDefinition, type Area, type CapabilityAgentSpec, type CapabilityCallContext, type CapabilityDefinition, type CapabilityErrorBody, type CapabilityErrorCode, type CapabilityErrorInit, type CapabilityId, type CapabilityManifest, type CapabilityPolicy, type FromZodErrorOptions, type JsonSchema, MONEY_META_KEY, MONEY_UNIT_SENTENCE, type ManifestEntry, type MoneyCurrency, type MoneyOptions, type MoneyView, type PolicyDecision, type PolicyEnforcement, type Role, type Surface };
package/dist/index.d.ts CHANGED
@@ -1,10 +1,7 @@
1
1
  import { z } from "zod/v4";
2
2
  import { MONEY_META_KEY, MONEY_UNIT_SENTENCE } from "@amboras-dev/money/ai";
3
- //#region src/canonical-json.d.ts
4
3
  /** Sorted keys, no whitespace. Throws on BigInt and circular values; `undefined` at the top serializes as `null`. */
5
4
  export declare function canonicalJson(v: unknown): string;
6
- //#endregion
7
- //#region src/ids.d.ts
8
5
  export declare const AREAS: readonly ["promotions", "catalog", "inventory", "setup", "content", "orders", "payments", "domains", "publish"];
9
6
  type Area = (typeof AREAS)[number];
10
7
  /** `<area>.<verb>` or `<area>.<entity>.<verb>`: lowercase segments of `a-z` and `_`. */
@@ -16,8 +13,6 @@ export declare const ROLE_RANK: Readonly<Record<Role, number>>;
16
13
  export declare function isCapabilityId(value: unknown): value is CapabilityId;
17
14
  /** The area an id belongs to (`promotions.create` → `promotions`). */
18
15
  export declare function areaOf(id: CapabilityId): Area;
19
- //#endregion
20
- //#region src/context.d.ts
21
16
  type Actor = {
22
17
  kind: 'member';
23
18
  profileId: string;
@@ -34,8 +29,6 @@ interface CapabilityCallContext {
34
29
  surface: Surface;
35
30
  runId?: string;
36
31
  }
37
- //#endregion
38
- //#region src/json-schema.d.ts
39
32
  type JsonSchema = {
40
33
  [key: string]: unknown;
41
34
  };
@@ -44,8 +37,6 @@ type JsonSchema = {
44
37
  * dropped from `required`. Adapters build the model-facing input with this.
45
38
  */
46
39
  export declare function omitFields(schema: JsonSchema, fields: readonly string[]): JsonSchema;
47
- //#endregion
48
- //#region src/policy-types.d.ts
49
40
  interface CapabilityPolicy {
50
41
  minRole: Role;
51
42
  planFeature?: string;
@@ -63,8 +54,6 @@ interface CapabilityPolicy {
63
54
  perMinute: number;
64
55
  };
65
56
  }
66
- //#endregion
67
- //#region src/define.d.ts
68
57
  interface CapabilityAgentSpec {
69
58
  /** What it does and when to use it, written for the model. */
70
59
  description: string;
@@ -107,8 +96,6 @@ interface CapabilityDefinition<I = unknown, O = unknown, Ctx = unknown> {
107
96
  * minRole, confirm threshold, rate limit or toolName.
108
97
  */
109
98
  export declare function defineCapability<I, O, Ctx = unknown>(def: CapabilityDefinition<I, O, Ctx>): Readonly<CapabilityDefinition<I, O, Ctx>>;
110
- //#endregion
111
- //#region src/errors.d.ts
112
99
  type CapabilityErrorCode = 'invalid_input' | 'forbidden' | 'not_found' | 'conflict' | 'confirmation_required' | 'rate_limited' | 'idempotency_conflict' | 'unavailable' | 'internal';
113
100
  interface CapabilityErrorBody {
114
101
  code: CapabilityErrorCode;
@@ -158,8 +145,6 @@ interface FromZodErrorOptions {
158
145
  * `options.renamed` for steering removed field names.
159
146
  */
160
147
  export declare function fromZodError(err: z.ZodError, options?: FromZodErrorOptions): CapabilityError;
161
- //#endregion
162
- //#region src/idempotency.d.ts
163
148
  /**
164
149
  * 8–100 of `A-Z a-z 0-9 . _ : -`. The underscore is there because the
165
150
  * orchestrator's key is `cap.{runId}.{toolCallId}` and model tool call ids
@@ -170,8 +155,6 @@ export declare const IDEMPOTENCY_KEY_PATTERN: RegExp;
170
155
  export declare function requiresIdempotencyKey(policy: Pick<CapabilityPolicy, 'effect' | 'idempotent'>): boolean;
171
156
  /** sha256 hex of canonicalJson({ id, input }): same key + different fingerprint = a different request. */
172
157
  export declare function requestFingerprint(id: CapabilityId, input: unknown): string;
173
- //#endregion
174
- //#region src/manifest.d.ts
175
158
  interface ManifestEntry {
176
159
  id: CapabilityId;
177
160
  version: number;
@@ -209,8 +192,6 @@ export declare function emitManifest(defs: readonly AnyCapabilityDefinition[], s
209
192
  * the file is read (the committed copy), not from the hash.
210
193
  */
211
194
  export declare function parseManifest(json: unknown): CapabilityManifest;
212
- //#endregion
213
- //#region src/money.d.ts
214
195
  /**
215
196
  * A bad amount or currency code. It is an `invalid_input` CapabilityError, so an
216
197
  * adapter that maps CapabilityError answers 400 with the rule (and the field,
@@ -286,8 +267,6 @@ export declare const moneyViewSchema: z.ZodType<MoneyView>;
286
267
  * unknown code throws `currency_invalid`.
287
268
  */
288
269
  export declare function moneyView(minor: number, currency: string): MoneyView;
289
- //#endregion
290
- //#region src/policy.d.ts
291
270
  /** Phase 1 adapters pass observe/observe. */
292
271
  interface PolicyEnforcement {
293
272
  role: 'enforce' | 'observe';
@@ -310,5 +289,4 @@ export declare function evaluatePolicy(policy: CapabilityPolicy, ctx: Capability
310
289
  * is not a non-negative integer, requires confirmation (the adapter could not count).
311
290
  */
312
291
  export declare function confirmationRequired(policy: Pick<CapabilityPolicy, 'confirm'>, records?: number): boolean;
313
- //#endregion
314
292
  export { type Actor, type AnyCapabilityDefinition, type Area, type CapabilityAgentSpec, type CapabilityCallContext, type CapabilityDefinition, type CapabilityErrorBody, type CapabilityErrorCode, type CapabilityErrorInit, type CapabilityId, type CapabilityManifest, type CapabilityPolicy, type FromZodErrorOptions, type JsonSchema, MONEY_META_KEY, MONEY_UNIT_SENTENCE, type ManifestEntry, type MoneyCurrency, type MoneyOptions, type MoneyView, type PolicyDecision, type PolicyEnforcement, type Role, type Surface };
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { z } from "zod/v4";
2
2
  import { currencyCode, fromMajor, money as money$1, storageDigits, storageScale as storageScale$1, toMajorNumber } from "@amboras-dev/money";
3
3
  import { MONEY_META_KEY, MONEY_UNIT_SENTENCE, moneyView as moneyView$1 } from "@amboras-dev/money/ai";
4
- //#region src/canonical-json.ts
4
+ // src/canonical-json.ts
5
5
  function serialize(value, seen) {
6
6
  if (value !== null && typeof value === "object" && typeof value.toJSON === "function") value = value.toJSON();
7
7
  if (value === null) return "null";
@@ -34,8 +34,7 @@ function serialize(value, seen) {
34
34
  function canonicalJson(v) {
35
35
  return serialize(v, /* @__PURE__ */ new Set()) ?? "null";
36
36
  }
37
- //#endregion
38
- //#region src/errors.ts
37
+ // src/errors.ts
39
38
  const STATUS = {
40
39
  invalid_input: 400,
41
40
  forbidden: 403,
@@ -164,8 +163,7 @@ function fromZodError(err, options = {}) {
164
163
  issues
165
164
  });
166
165
  }
167
- //#endregion
168
- //#region src/ids.ts
166
+ // src/ids.ts
169
167
  const AREAS = [
170
168
  "promotions",
171
169
  "catalog",
@@ -196,8 +194,7 @@ function areaOf(id) {
196
194
  function isRole(value) {
197
195
  return value === "owner" || value === "manager" || value === "staff";
198
196
  }
199
- //#endregion
200
- //#region src/money.ts
197
+ // src/money.ts
201
198
  /**
202
199
  * A bad amount or currency code. It is an `invalid_input` CapabilityError, so an
203
200
  * adapter that maps CapabilityError answers 400 with the rule (and the field,
@@ -353,8 +350,7 @@ function moneyView(minor, currency) {
353
350
  throw toCapabilityMoneyError(error);
354
351
  }
355
352
  }
356
- //#endregion
357
- //#region src/json-schema.ts
353
+ // src/json-schema.ts
358
354
  /**
359
355
  * The exact conversion every manifest uses. Throws for types JSON Schema cannot
360
356
  * express. Every money() field gets its marker back, and its unit sentence when
@@ -432,8 +428,7 @@ function omitFields(schema, fields) {
432
428
  }
433
429
  return copy;
434
430
  }
435
- //#endregion
436
- //#region src/guards.ts
431
+ // src/guards.ts
437
432
  /**
438
433
  * Tenant and actor ids come from the call context, never from input. A name is
439
434
  * refused when, lower-cased with separators removed, it ends in one of these
@@ -586,8 +581,7 @@ function checkEntry(entry) {
586
581
  if (typeof entry.agent.description !== "string" || entry.agent.description.trim() === "") fail(id, "agent.description is required");
587
582
  if (entry.agent.toolName !== void 0 && !TOOL_NAME.test(entry.agent.toolName)) fail(id, `agent.toolName must match ${TOOL_NAME}`);
588
583
  }
589
- //#endregion
590
- //#region src/define.ts
584
+ // src/define.ts
591
585
  function convert(schema, io, id) {
592
586
  try {
593
587
  return toJsonSchema(schema, io);
@@ -637,8 +631,7 @@ function defineCapability(def) {
637
631
  agent: freezeCopy(def.agent)
638
632
  });
639
633
  }
640
- //#endregion
641
- //#region src/sha256.ts
634
+ // src/sha256.ts
642
635
  const K = new Uint32Array([
643
636
  1116352408,
644
637
  1899447441,
@@ -781,8 +774,7 @@ function sha256Hex(text) {
781
774
  for (const word of h) hex += word.toString(16).padStart(8, "0");
782
775
  return hex;
783
776
  }
784
- //#endregion
785
- //#region src/idempotency.ts
777
+ // src/idempotency.ts
786
778
  /**
787
779
  * 8–100 of `A-Z a-z 0-9 . _ : -`. The underscore is there because the
788
780
  * orchestrator's key is `cap.{runId}.{toolCallId}` and model tool call ids
@@ -800,8 +792,7 @@ function requestFingerprint(id, input) {
800
792
  input
801
793
  }));
802
794
  }
803
- //#endregion
804
- //#region src/manifest.ts
795
+ // src/manifest.ts
805
796
  const hashOf = (capabilities) => sha256Hex(canonicalJson(capabilities));
806
797
  /** Plain JSON with keys sorted at every level, so the committed file is stable text. */
807
798
  const sortedJson = (value) => JSON.parse(canonicalJson(value));
@@ -925,8 +916,7 @@ function parseManifest(json) {
925
916
  if (actual !== manifest.hash) throw new CapabilityManifestError(`Capability manifest hash mismatch: header ${manifest.hash}, content ${actual}`);
926
917
  return manifest;
927
918
  }
928
- //#endregion
929
- //#region src/policy.ts
919
+ // src/policy.ts
930
920
  function roleCheck(policy, ctx) {
931
921
  const { actor } = ctx;
932
922
  if (actor.kind === "internal") return null;
@@ -1013,5 +1003,4 @@ function confirmationRequired(policy, records) {
1013
1003
  if (typeof records !== "number" || !Number.isInteger(records) || records < 0) return true;
1014
1004
  return records >= confirm.when.recordsAtLeast;
1015
1005
  }
1016
- //#endregion
1017
1006
  export { AREAS, CapabilityDefinitionError, CapabilityError, CapabilityManifestError, IDEMPOTENCY_KEY_PATTERN, MONEY_META_KEY, MONEY_UNIT_SENTENCE, MoneyError, ROLE_RANK, areaOf, canonicalJson, confirmationRequired, defineCapability, emitManifest, evaluatePolicy, fractionDigits, fromStorageAmount, fromZodError, httpStatusFor, isCapabilityId, money, moneyView, moneyViewSchema, omitFields, parseManifest, requestFingerprint, requiresIdempotencyKey, storageScale, toStorageAmount };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@amboras-dev/capability-kit",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "description": "Capability contract for Amboras: defineCapability, major-unit money (on @amboras-dev/money), the shared error contract, pure policy evaluation, idempotency helpers and a deterministic manifest. Peer dependency on zod.",
5
5
  "license": "UNLICENSED",
6
6
  "repository": {
@@ -36,25 +36,26 @@
36
36
  "access": "public"
37
37
  },
38
38
  "dependencies": {
39
- "@amboras-dev/money": "0.2.0"
39
+ "@amboras-dev/money": "0.3.0"
40
40
  },
41
41
  "peerDependencies": {
42
- "zod": "^3.25.76 || ^4.0.0"
42
+ "zod": "^3.25.76 || ^4.6.6"
43
43
  },
44
44
  "devDependencies": {
45
45
  "@types/node": "22.20.5",
46
- "@vitest/coverage-v8": "3.2.7",
46
+ "@vitest/coverage-v8": "5.0.5",
47
47
  "fast-check": "4.3.0",
48
48
  "tsdown": "0.23.0",
49
49
  "typescript": "5.9.3",
50
- "vitest": "3.2.7",
51
- "zod": "4.3.6",
50
+ "vite": "8.3.5",
51
+ "vitest": "5.0.5",
52
+ "zod": "4.6.7",
52
53
  "zod3": "npm:zod@3.25.76",
53
- "zod40": "npm:zod@4.0.0"
54
+ "zod46": "npm:zod@4.6.6"
54
55
  },
55
56
  "scripts": {
56
57
  "build": "tsdown",
57
- "typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.test.json && tsc --noEmit -p tsconfig.zod3.json && tsc --noEmit -p tsconfig.zod40.json",
58
- "test": "vitest run --coverage && vitest run --config vitest.zod3.config.ts && vitest run --config vitest.zod40.config.ts"
58
+ "typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.test.json && tsc --noEmit -p tsconfig.zod3.json && tsc --noEmit -p tsconfig.zod46.json",
59
+ "test": "vitest run --coverage && vitest run --config vitest.zod3.config.ts && vitest run --config vitest.zod46.config.ts"
59
60
  }
60
61
  }