@agentproto/policy 0.1.0-alpha.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 agentproto contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,23 @@
1
+ # @agentproto/policy
2
+
3
+ AIP-38 `POLICY.md` reference implementation. A markdown + frontmatter format for declaring policy on a resource — access grants (who can perform which actions), defaults (per-block behavioural defaults), limits (rate / quota caps), and requirements (cross-cutting must-haves like MFA / approval). Composable inline | ref | file. Granted on AIP-39 ACTION ids — implementations / TOOLs are decoupled from policy.
4
+
5
+ > **Status: 0.1.0-alpha.** Generated by `scripts/scaffold-aip.mjs` — `build()` and `validate()` bodies are TODOs.
6
+
7
+ Spec: <https://agentproto.sh/docs/aip-38>
8
+
9
+ ## Usage
10
+
11
+ ```ts
12
+ import { definePolicy } from "@agentproto/policy"
13
+
14
+ const x = definePolicy({
15
+ id: "my-policy",
16
+ description: "Short purpose.",
17
+ // ...
18
+ })
19
+ ```
20
+
21
+ ## License
22
+
23
+ MIT — see [LICENSE](./LICENSE).
@@ -0,0 +1,29 @@
1
+ import { z } from 'zod';
2
+ import { createDoctype } from '@agentproto/define-doctype';
3
+
4
+ /**
5
+ * @agentproto/policy v0.1.0-alpha
6
+ * AIP-38 POLICY.md `definePolicy` reference implementation.
7
+ */
8
+
9
+ var policyFrontmatterSchema = z.object({ "schema": z.literal("policy/v1"), "id": z.string().regex(new RegExp("^@[a-z0-9][a-z0-9-]*/[a-z0-9][a-z0-9-]*$")).describe("Standalone-only. Globally addressable id `@<owner-slug>/<policy-slug>`.").optional(), "version": z.string().regex(new RegExp("^\\d+\\.\\d+\\.\\d+(?:[-+][\\w.\\-]+)?$")).describe("Standalone-only. Spec version of THIS file.").optional(), "default": z.enum(["allow", "deny"]).describe("Default decision when no grant matches. `deny` strongly recommended; `allow` is audit-significant.").default("deny"), "grants": z.array(z.any()).describe("Access grants. Each grant ties a principal (AIP-23) to a set of actions (AIP-39).").default([]), "defaults": z.record(z.string(), z.record(z.string(), z.any())).describe("Per-block behavioural defaults. Keys are AIP block names (storage, sandbox, code, secrets); values are partial block configs.").default({}), "limits": z.array(z.any()).describe("Resource limits. Each `{ kind, value, scope?, per?, applies_to? }`.").default([]), "requirements": z.array(z.any()).describe("Cross-cutting must-haves (MFA, signing, approvals). ANDed across composed policies.").default([]), "metadata": z.record(z.string(), z.any()).describe("Free-form, namespaced.").optional() }).strict().describe("Validates the YAML frontmatter portion of an AIP-38 POLICY.md manifest, OR the inline form embedded in any other manifest's `policy:` block. Grants on AIP-39 ACTION ids; principals via AIP-23 identity-ref schemes.");
10
+ var definePolicy = createDoctype({
11
+ aip: 38,
12
+ name: "policy",
13
+ readDescription: false,
14
+ validate(def) {
15
+ const result = policyFrontmatterSchema.safeParse(def);
16
+ if (!result.success) {
17
+ throw new Error(
18
+ `definePolicy (AIP-38): ${result.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join("; ")}`
19
+ );
20
+ }
21
+ },
22
+ build(def) {
23
+ return { ...def };
24
+ }
25
+ });
26
+
27
+ export { definePolicy, policyFrontmatterSchema };
28
+ //# sourceMappingURL=chunk-DS2TYMHI.mjs.map
29
+ //# sourceMappingURL=chunk-DS2TYMHI.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/schema.ts","../src/define-policy.ts"],"names":[],"mappings":";;;;;;;;AAeO,IAAM,uBAAA,GAA0B,CAAA,CAAE,MAAA,CAAO,EAAE,QAAA,EAAU,CAAA,CAAE,OAAA,CAAQ,WAAW,CAAA,EAAG,IAAA,EAAM,CAAA,CAAE,MAAA,GAAS,KAAA,CAAM,IAAI,MAAA,CAAO,0CAA0C,CAAC,CAAA,CAAE,QAAA,CAAS,yEAAyE,EAAE,QAAA,EAAS,EAAG,SAAA,EAAW,CAAA,CAAE,MAAA,EAAO,CAAE,KAAA,CAAM,IAAI,OAAO,yCAAyC,CAAC,CAAA,CAAE,QAAA,CAAS,6CAA6C,CAAA,CAAE,QAAA,EAAS,EAAG,WAAW,CAAA,CAAE,IAAA,CAAK,CAAC,OAAA,EAAQ,MAAM,CAAC,CAAA,CAAE,QAAA,CAAS,oGAAoG,CAAA,CAAE,OAAA,CAAQ,MAAM,CAAA,EAAG,QAAA,EAAU,CAAA,CAAE,KAAA,CAAM,CAAA,CAAE,KAAK,CAAA,CAAE,QAAA,CAAS,mFAAmF,CAAA,CAAE,OAAA,CAAQ,EAAW,GAAG,UAAA,EAAY,CAAA,CAAE,MAAA,CAAO,CAAA,CAAE,MAAA,EAAO,EAAG,CAAA,CAAE,MAAA,CAAO,CAAA,CAAE,MAAA,EAAO,EAAG,CAAA,CAAE,GAAA,EAAK,CAAC,CAAA,CAAE,SAAS,+HAA+H,CAAA,CAAE,OAAA,CAAQ,EAAW,CAAA,EAAG,QAAA,EAAU,CAAA,CAAE,MAAM,CAAA,CAAE,GAAA,EAAK,CAAA,CAAE,QAAA,CAAS,qEAAqE,CAAA,CAAE,OAAA,CAAQ,EAAW,CAAA,EAAG,cAAA,EAAgB,CAAA,CAAE,KAAA,CAAM,CAAA,CAAE,GAAA,EAAK,EAAE,QAAA,CAAS,qFAAqF,CAAA,CAAE,OAAA,CAAQ,EAAW,CAAA,EAAG,UAAA,EAAY,EAAE,MAAA,CAAO,CAAA,CAAE,MAAA,EAAO,EAAG,CAAA,CAAE,GAAA,EAAK,CAAA,CAAE,SAAS,wBAAwB,CAAA,CAAE,QAAA,EAAS,EAAG,CAAA,CAAE,MAAA,EAAO,CAAE,SAAS,uNAAuN;ACMlgD,IAAM,eAAe,aAAA,CAA8C;AAAA,EACxE,GAAA,EAAK,EAAA;AAAA,EACL,IAAA,EAAM,QAAA;AAAA,EACN,eAAA,EAAiB,KAAA;AAAA,EACjB,SAAS,GAAA,EAAK;AACZ,IAAA,MAAM,MAAA,GAAS,uBAAA,CAAwB,SAAA,CAAU,GAAG,CAAA;AACpD,IAAA,IAAI,CAAC,OAAO,OAAA,EAAS;AACnB,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAA,uBAAA,EAA0B,OAAO,KAAA,CAAM,MAAA,CACpC,IAAI,CAAC,CAAA,KAAM,GAAG,CAAA,CAAE,IAAA,CAAK,KAAK,GAAG,CAAC,KAAK,CAAA,CAAE,OAAO,EAAE,CAAA,CAC9C,IAAA,CAAK,IAAI,CAAC,CAAA;AAAA,OACf;AAAA,IACF;AAAA,EAIF,CAAA;AAAA,EACA,MAAM,GAAA,EAAK;AAKT,IAAA,OAAO,EAAE,GAAG,GAAA,EAAI;AAAA,EAClB;AACF,CAAC","file":"chunk-DS2TYMHI.mjs","sourcesContent":["/**\n * AIP-38 POLICY.md frontmatter zod schema.\n *\n * Generated from `resources/aip-38/draft/POLICY.schema.json` via\n * json-schema-to-zod. Imported by both `define-policy.ts` (TS path\n * validation) and `manifest/index.ts` (.md path validation) so every\n * field-level constraint runs in both authoring paths from a single\n * source of truth — re-run scaffold-aip to refresh after spec changes.\n *\n * Cross-field rules (if/then/allOf in JSON Schema) don't translate\n * cleanly and live in `define-policy.ts`'s `validate(def)` instead.\n */\n\nimport { z } from \"zod\"\n\nexport const policyFrontmatterSchema = z.object({ \"schema\": z.literal(\"policy/v1\"), \"id\": z.string().regex(new RegExp(\"^@[a-z0-9][a-z0-9-]*/[a-z0-9][a-z0-9-]*$\")).describe(\"Standalone-only. Globally addressable id `@<owner-slug>/<policy-slug>`.\").optional(), \"version\": z.string().regex(new RegExp(\"^\\\\d+\\\\.\\\\d+\\\\.\\\\d+(?:[-+][\\\\w.\\\\-]+)?$\")).describe(\"Standalone-only. Spec version of THIS file.\").optional(), \"default\": z.enum([\"allow\",\"deny\"]).describe(\"Default decision when no grant matches. `deny` strongly recommended; `allow` is audit-significant.\").default(\"deny\"), \"grants\": z.array(z.any()).describe(\"Access grants. Each grant ties a principal (AIP-23) to a set of actions (AIP-39).\").default([] as never), \"defaults\": z.record(z.string(), z.record(z.string(), z.any())).describe(\"Per-block behavioural defaults. Keys are AIP block names (storage, sandbox, code, secrets); values are partial block configs.\").default({} as never), \"limits\": z.array(z.any()).describe(\"Resource limits. Each `{ kind, value, scope?, per?, applies_to? }`.\").default([] as never), \"requirements\": z.array(z.any()).describe(\"Cross-cutting must-haves (MFA, signing, approvals). ANDed across composed policies.\").default([] as never), \"metadata\": z.record(z.string(), z.any()).describe(\"Free-form, namespaced.\").optional() }).strict().describe(\"Validates the YAML frontmatter portion of an AIP-38 POLICY.md manifest, OR the inline form embedded in any other manifest's `policy:` block. Grants on AIP-39 ACTION ids; principals via AIP-23 identity-ref schemes.\")\n\nexport type PolicyFrontmatter = z.infer<typeof policyFrontmatterSchema>\n","import { createDoctype } from \"@agentproto/define-doctype\"\nimport { policyFrontmatterSchema } from \"./schema.js\"\nimport type { PolicyDefinition, PolicyHandle } from \"./types.js\"\n\n/**\n * AIP-38 reference implementation of `definePolicy`.\n *\n * Built on `createDoctype` so the cross-AIP invariants (id pattern,\n * description length, top-level freeze, \"definePolicy (AIP-38): …\"\n * error prefix) run uniformly with every other AIP defineX.\n *\n * Field-level validation runs the schema-derived zod from\n * `./schema.ts` against the input. Same source of truth as the .md\n * path uses (`parsePolicyManifest`), so a malformed TS-authored\n * definition fails with the same diagnostic as a malformed manifest.\n * Cross-field rules go in `validate(def)` after the zod check.\n *\n * Identity / description extractors detected from the JSON Schema:\n * readIdentity: def.id\n * readDescription: skipped (no string-y required field detected).\n */\nexport const definePolicy = createDoctype<PolicyDefinition, PolicyHandle>({\n aip: 38,\n name: \"policy\",\n readDescription: false,\n validate(def) {\n const result = policyFrontmatterSchema.safeParse(def)\n if (!result.success) {\n throw new Error(\n `definePolicy (AIP-38): ${result.error.issues\n .map((i) => `${i.path.join(\".\")}: ${i.message}`)\n .join(\"; \")}`,\n )\n }\n // TODO: spec-38-specific cross-field rules (if/then/allOf in\n // the JSON Schema) — those don't translate to zod cleanly and\n // belong here. See @agentproto/operator's autonomy=gated rule.\n },\n build(def) {\n // Default build: spread the validated definition into a fresh object.\n // Hand-tune for nested freezing (Object.freeze on arrays/objects) and\n // for fields that need defaults applied — see @agentproto/operator\n // for a reference shape.\n return { ...def } as PolicyHandle\n },\n})\n"]}
@@ -0,0 +1,38 @@
1
+ import { P as PolicyDefinition } from './schema-ALC4Y3-2.js';
2
+ export { a as PolicyFrontmatter, b as PolicyHandle, p as policyFrontmatterSchema } from './schema-ALC4Y3-2.js';
3
+ import 'zod';
4
+
5
+ /**
6
+ * AIP-38 reference implementation of `definePolicy`.
7
+ *
8
+ * Built on `createDoctype` so the cross-AIP invariants (id pattern,
9
+ * description length, top-level freeze, "definePolicy (AIP-38): …"
10
+ * error prefix) run uniformly with every other AIP defineX.
11
+ *
12
+ * Field-level validation runs the schema-derived zod from
13
+ * `./schema.ts` against the input. Same source of truth as the .md
14
+ * path uses (`parsePolicyManifest`), so a malformed TS-authored
15
+ * definition fails with the same diagnostic as a malformed manifest.
16
+ * Cross-field rules go in `validate(def)` after the zod check.
17
+ *
18
+ * Identity / description extractors detected from the JSON Schema:
19
+ * readIdentity: def.id
20
+ * readDescription: skipped (no string-y required field detected).
21
+ */
22
+ declare const definePolicy: (def: PolicyDefinition) => Readonly<PolicyDefinition>;
23
+
24
+ /**
25
+ * @agentproto/policy — AIP-38 POLICY.md `definePolicy` reference impl.
26
+ *
27
+ * A markdown + frontmatter format for declaring policy on a resource — access grants (who can perform which actions), defaults (per-block behavioural defaults), limits (rate / quota caps), and requirements (cross-cutting must-haves like MFA / approval). Composable inline | ref | file. Granted on AIP-39 ACTION ids — implementations / TOOLs are decoupled from policy.
28
+ *
29
+ * Spec: https://agentproto.sh/docs/aip-38
30
+ *
31
+ * Authoring paths:
32
+ * - TS: `definePolicy({...})` → `PolicyHandle`
33
+ * - MD: `parsePolicyManifest(src) → policyFromManifest({...})` → `PolicyHandle`
34
+ */
35
+ declare const SPEC_NAME: "agentpolicy/v1";
36
+ declare const SPEC_VERSION: "1.0.0-alpha";
37
+
38
+ export { PolicyDefinition, SPEC_NAME, SPEC_VERSION, definePolicy };
package/dist/index.mjs ADDED
@@ -0,0 +1,14 @@
1
+ export { definePolicy, policyFrontmatterSchema } from './chunk-DS2TYMHI.mjs';
2
+
3
+ /**
4
+ * @agentproto/policy v0.1.0-alpha
5
+ * AIP-38 POLICY.md `definePolicy` reference implementation.
6
+ */
7
+
8
+ // src/index.ts
9
+ var SPEC_NAME = "agentpolicy/v1";
10
+ var SPEC_VERSION = "1.0.0-alpha";
11
+
12
+ export { SPEC_NAME, SPEC_VERSION };
13
+ //# sourceMappingURL=index.mjs.map
14
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;AAYO,IAAM,SAAA,GAAY;AAClB,IAAM,YAAA,GAAe","file":"index.mjs","sourcesContent":["/**\n * @agentproto/policy — AIP-38 POLICY.md `definePolicy` reference impl.\n *\n * A markdown + frontmatter format for declaring policy on a resource — access grants (who can perform which actions), defaults (per-block behavioural defaults), limits (rate / quota caps), and requirements (cross-cutting must-haves like MFA / approval). Composable inline | ref | file. Granted on AIP-39 ACTION ids — implementations / TOOLs are decoupled from policy.\n *\n * Spec: https://agentproto.sh/docs/aip-38\n *\n * Authoring paths:\n * - TS: `definePolicy({...})` → `PolicyHandle`\n * - MD: `parsePolicyManifest(src) → policyFromManifest({...})` → `PolicyHandle`\n */\n\nexport const SPEC_NAME = \"agentpolicy/v1\" as const\nexport const SPEC_VERSION = \"1.0.0-alpha\" as const\n\nexport { definePolicy } from \"./define-policy.js\"\nexport { policyFrontmatterSchema } from \"./schema.js\"\nexport type { PolicyFrontmatter } from \"./schema.js\"\nexport type { PolicyDefinition, PolicyHandle } from \"./types.js\"\n"]}
@@ -0,0 +1,28 @@
1
+ import { a as PolicyFrontmatter, b as PolicyHandle } from '../schema-ALC4Y3-2.js';
2
+ export { p as policyFrontmatterSchema } from '../schema-ALC4Y3-2.js';
3
+ import 'zod';
4
+
5
+ /**
6
+ * AIP-38 POLICY.md sidecar parser + manifest-to-handle constructor.
7
+ *
8
+ * Mirror of `@agentproto/tool/manifest` and `@agentproto/driver/manifest`:
9
+ * the .md provides metadata; the TS module supplies any spec-specific
10
+ * runtime bits (schemas, execute bodies, …) that can't live in
11
+ * frontmatter. Both inputs end up in `definePolicy` so the cross-AIP
12
+ * invariants run uniformly.
13
+ *
14
+ *
15
+ * The frontmatter zod schema below was generated from
16
+ * `resources/aip-38/draft/POLICY.schema.json` via json-schema-to-zod.
17
+ * Re-run scaffold-aip to refresh after spec changes (or hand-tune
18
+ * any constraint the converter doesn't capture cleanly).
19
+ */
20
+
21
+ interface PolicyManifest {
22
+ frontmatter: PolicyFrontmatter;
23
+ body: string;
24
+ }
25
+ declare function parsePolicyManifest(source: string): PolicyManifest;
26
+ declare function policyFromManifest(manifest: PolicyManifest): PolicyHandle;
27
+
28
+ export { PolicyFrontmatter, type PolicyManifest, parsePolicyManifest, policyFromManifest };
@@ -0,0 +1,28 @@
1
+ import { policyFrontmatterSchema, definePolicy } from '../chunk-DS2TYMHI.mjs';
2
+ export { policyFrontmatterSchema } from '../chunk-DS2TYMHI.mjs';
3
+ import matter from 'gray-matter';
4
+
5
+ /**
6
+ * @agentproto/policy v0.1.0-alpha
7
+ * AIP-38 POLICY.md `definePolicy` reference implementation.
8
+ */
9
+ function parsePolicyManifest(source) {
10
+ const parsed = matter(source);
11
+ if (Object.keys(parsed.data).length === 0) {
12
+ throw new Error("parsePolicyManifest: missing or empty frontmatter");
13
+ }
14
+ const result = policyFrontmatterSchema.safeParse(parsed.data);
15
+ if (!result.success) {
16
+ throw new Error(
17
+ `parsePolicyManifest: invalid frontmatter \u2014 ${result.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join("; ")}`
18
+ );
19
+ }
20
+ return { frontmatter: result.data, body: parsed.content };
21
+ }
22
+ function policyFromManifest(manifest) {
23
+ return definePolicy(manifest.frontmatter);
24
+ }
25
+
26
+ export { parsePolicyManifest, policyFromManifest };
27
+ //# sourceMappingURL=index.mjs.map
28
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/manifest/index.ts"],"names":[],"mappings":";;;;;;;;AA8BO,SAAS,oBAAoB,MAAA,EAAgC;AAClE,EAAA,MAAM,MAAA,GAAS,OAAO,MAAM,CAAA;AAC5B,EAAA,IAAI,OAAO,IAAA,CAAK,MAAA,CAAO,IAAI,CAAA,CAAE,WAAW,CAAA,EAAG;AACzC,IAAA,MAAM,IAAI,MAAM,mDAAmD,CAAA;AAAA,EACrE;AACA,EAAA,MAAM,MAAA,GAAS,uBAAA,CAAwB,SAAA,CAAU,MAAA,CAAO,IAAI,CAAA;AAC5D,EAAA,IAAI,CAAC,OAAO,OAAA,EAAS;AACnB,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,gDAAA,EAA8C,OAAO,KAAA,CAAM,MAAA,CACxD,IAAI,CAAC,CAAA,KAAM,GAAG,CAAA,CAAE,IAAA,CAAK,KAAK,GAAG,CAAC,KAAK,CAAA,CAAE,OAAO,EAAE,CAAA,CAC9C,IAAA,CAAK,IAAI,CAAC,CAAA;AAAA,KACf;AAAA,EACF;AACA,EAAA,OAAO,EAAE,WAAA,EAAa,MAAA,CAAO,IAAA,EAAM,IAAA,EAAM,OAAO,OAAA,EAAQ;AAC1D;AAEO,SAAS,mBAAmB,QAAA,EAAwC;AAKzE,EAAA,OAAO,YAAA,CAAa,SAAS,WAA0C,CAAA;AACzE","file":"index.mjs","sourcesContent":["/**\n * AIP-38 POLICY.md sidecar parser + manifest-to-handle constructor.\n *\n * Mirror of `@agentproto/tool/manifest` and `@agentproto/driver/manifest`:\n * the .md provides metadata; the TS module supplies any spec-specific\n * runtime bits (schemas, execute bodies, …) that can't live in\n * frontmatter. Both inputs end up in `definePolicy` so the cross-AIP\n * invariants run uniformly.\n *\n *\n * The frontmatter zod schema below was generated from\n * `resources/aip-38/draft/POLICY.schema.json` via json-schema-to-zod.\n * Re-run scaffold-aip to refresh after spec changes (or hand-tune\n * any constraint the converter doesn't capture cleanly).\n */\n\nimport matter from \"gray-matter\"\nimport { policyFrontmatterSchema, type PolicyFrontmatter } from \"../schema.js\"\nimport { definePolicy } from \"../define-policy.js\"\nimport type { PolicyDefinition, PolicyHandle } from \"../types.js\"\n\n// Re-export so consumers can import the schema + inferred type either\n// from \"@@agentproto/policy/manifest\" or directly from \"@@agentproto/policy/schema\".\nexport { policyFrontmatterSchema, type PolicyFrontmatter }\n\nexport interface PolicyManifest {\n frontmatter: PolicyFrontmatter\n body: string\n}\n\nexport function parsePolicyManifest(source: string): PolicyManifest {\n const parsed = matter(source)\n if (Object.keys(parsed.data).length === 0) {\n throw new Error(\"parsePolicyManifest: missing or empty frontmatter\")\n }\n const result = policyFrontmatterSchema.safeParse(parsed.data)\n if (!result.success) {\n throw new Error(\n `parsePolicyManifest: invalid frontmatter — ${result.error.issues\n .map((i) => `${i.path.join(\".\")}: ${i.message}`)\n .join(\"; \")}`,\n )\n }\n return { frontmatter: result.data, body: parsed.content }\n}\n\nexport function policyFromManifest(manifest: PolicyManifest): PolicyHandle {\n // The zod-validated frontmatter is structurally compatible with\n // PolicyDefinition; the cast pins the typing once the manifest\n // schema and the TS interface diverge (e.g. handle has frozen fields\n // a literal config doesn't carry yet).\n return definePolicy(manifest.frontmatter as unknown as PolicyDefinition)\n}\n"]}
@@ -0,0 +1,196 @@
1
+ import { z } from 'zod';
2
+
3
+ /**
4
+ * AIP-38 PolicyDefinition + PolicyHandle.
5
+ *
6
+ * `PolicyDefinition` was generated from
7
+ * `resources/aip-38/draft/POLICY.schema.json` via json-schema-to-typescript.
8
+ * `PolicyHandle` is the readonly view of the same shape; tighten it
9
+ * by hand for fields that get defaults applied in build().
10
+ */
11
+ /**
12
+ * Validates the YAML frontmatter portion of an AIP-38 POLICY.md manifest, OR the inline form embedded in any other manifest's `policy:` block. Grants on AIP-39 ACTION ids; principals via AIP-23 identity-ref schemes.
13
+ */
14
+ interface PolicyDefinition {
15
+ schema: "policy/v1";
16
+ /**
17
+ * Standalone-only. Globally addressable id `@<owner-slug>/<policy-slug>`.
18
+ */
19
+ id?: string;
20
+ /**
21
+ * Standalone-only. Spec version of THIS file.
22
+ */
23
+ version?: string;
24
+ /**
25
+ * Default decision when no grant matches. `deny` strongly recommended; `allow` is audit-significant.
26
+ */
27
+ default?: "allow" | "deny";
28
+ /**
29
+ * Access grants. Each grant ties a principal (AIP-23) to a set of actions (AIP-39).
30
+ */
31
+ grants?: Grant[];
32
+ /**
33
+ * Per-block behavioural defaults. Keys are AIP block names (storage, sandbox, code, secrets); values are partial block configs.
34
+ */
35
+ defaults?: {
36
+ [k: string]: {
37
+ [k: string]: unknown;
38
+ };
39
+ };
40
+ /**
41
+ * Resource limits. Each `{ kind, value, scope?, per?, applies_to? }`.
42
+ */
43
+ limits?: Limit[];
44
+ /**
45
+ * Cross-cutting must-haves (MFA, signing, approvals). ANDed across composed policies.
46
+ */
47
+ requirements?: Requirement[];
48
+ /**
49
+ * Free-form, namespaced.
50
+ */
51
+ metadata?: {
52
+ [k: string]: unknown;
53
+ };
54
+ }
55
+ interface Grant {
56
+ /**
57
+ * AIP-23 identity-ref. Schemes: operator://, user://, org://, guild://, bot://, group://, role://, *.
58
+ */
59
+ principal: {
60
+ name: string;
61
+ email: string;
62
+ avatar?: string;
63
+ gpg_key?: string;
64
+ role?: string;
65
+ metadata?: {};
66
+ [k: string]: unknown;
67
+ } | {
68
+ ref: string;
69
+ role?: string;
70
+ [k: string]: unknown;
71
+ } | {
72
+ file: string;
73
+ role?: string;
74
+ [k: string]: unknown;
75
+ } | string;
76
+ /**
77
+ * @minItems 1
78
+ */
79
+ actions: [ActionGrant, ...ActionGrant[]];
80
+ /**
81
+ * Conditions ANDed (all must hold). Unknown conditions skip the grant.
82
+ */
83
+ conditions?: Condition[];
84
+ /**
85
+ * Time-bound grant; expires at granted_at + ttl_seconds.
86
+ */
87
+ ttl_seconds?: number;
88
+ /**
89
+ * ISO 8601. Audit metadata.
90
+ */
91
+ granted_at?: string;
92
+ /**
93
+ * Who issued this grant. Audit metadata.
94
+ */
95
+ granted_by?: {
96
+ name: string;
97
+ email: string;
98
+ avatar?: string;
99
+ gpg_key?: string;
100
+ role?: string;
101
+ metadata?: {};
102
+ [k: string]: unknown;
103
+ } | {
104
+ ref: string;
105
+ role?: string;
106
+ [k: string]: unknown;
107
+ } | {
108
+ file: string;
109
+ role?: string;
110
+ [k: string]: unknown;
111
+ } | string;
112
+ /**
113
+ * Soft-revoke marker. A revoked grant evaluates as no-grant.
114
+ */
115
+ revoked?: boolean;
116
+ }
117
+ interface ActionGrant {
118
+ /**
119
+ * AIP-39 ACTION reference. Bare id (e.g. `storage:commit`), workspace-relative path, or registry slug (`@agentik/actions/standard/storage-commit`). `*` suffix permits wildcards (`storage:*`).
120
+ */
121
+ action: string;
122
+ /**
123
+ * Optional scope narrowing for this grant (action-specific).
124
+ */
125
+ scope?: string;
126
+ }
127
+ interface Condition {
128
+ /**
129
+ * Condition kind. Standard: `during-business-hours`, `ip-range`, `mfa-recent`, `approval-from`, `signed-by`. Hosts MAY register custom kinds.
130
+ */
131
+ kind: string;
132
+ [k: string]: unknown;
133
+ }
134
+ interface Limit {
135
+ /**
136
+ * Limit kind. Standard: `max-concurrent-sandboxes`, `rate-tool-calls`, `max-egress-bytes-per-day`. Host-extensible.
137
+ */
138
+ kind: string;
139
+ value: number;
140
+ /**
141
+ * Per what? `user`, `workspace`, `org`, host-specific.
142
+ */
143
+ scope?: string;
144
+ /**
145
+ * For rate-style limits.
146
+ */
147
+ per?: "second" | "minute" | "hour" | "day";
148
+ /**
149
+ * Action refs the limit applies to. Empty / missing = all actions.
150
+ */
151
+ applies_to?: string[];
152
+ [k: string]: unknown;
153
+ }
154
+ interface Requirement {
155
+ /**
156
+ * Requirement kind. Standard: `mfa-recent`, `signed-by`, `approval-from`. Host-extensible.
157
+ */
158
+ kind: string;
159
+ /**
160
+ * Action refs this requirement applies to. Empty / missing = all actions.
161
+ */
162
+ applies_to?: string[];
163
+ [k: string]: unknown;
164
+ }
165
+ type PolicyHandle = Readonly<PolicyDefinition>;
166
+
167
+ /**
168
+ * AIP-38 POLICY.md frontmatter zod schema.
169
+ *
170
+ * Generated from `resources/aip-38/draft/POLICY.schema.json` via
171
+ * json-schema-to-zod. Imported by both `define-policy.ts` (TS path
172
+ * validation) and `manifest/index.ts` (.md path validation) so every
173
+ * field-level constraint runs in both authoring paths from a single
174
+ * source of truth — re-run scaffold-aip to refresh after spec changes.
175
+ *
176
+ * Cross-field rules (if/then/allOf in JSON Schema) don't translate
177
+ * cleanly and live in `define-policy.ts`'s `validate(def)` instead.
178
+ */
179
+
180
+ declare const policyFrontmatterSchema: z.ZodObject<{
181
+ schema: z.ZodLiteral<"policy/v1">;
182
+ id: z.ZodOptional<z.ZodString>;
183
+ version: z.ZodOptional<z.ZodString>;
184
+ default: z.ZodDefault<z.ZodEnum<{
185
+ allow: "allow";
186
+ deny: "deny";
187
+ }>>;
188
+ grants: z.ZodDefault<z.ZodArray<z.ZodAny>>;
189
+ defaults: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodAny>>>;
190
+ limits: z.ZodDefault<z.ZodArray<z.ZodAny>>;
191
+ requirements: z.ZodDefault<z.ZodArray<z.ZodAny>>;
192
+ metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
193
+ }, z.core.$strict>;
194
+ type PolicyFrontmatter = z.infer<typeof policyFrontmatterSchema>;
195
+
196
+ export { type PolicyDefinition as P, type PolicyFrontmatter as a, type PolicyHandle as b, policyFrontmatterSchema as p };
package/package.json ADDED
@@ -0,0 +1,68 @@
1
+ {
2
+ "name": "@agentproto/policy",
3
+ "version": "0.1.0-alpha.0",
4
+ "description": "@agentproto/policy — AIP-38 POLICY.md reference implementation. A markdown + frontmatter format for declaring policy on a resource — access grants (who can perform which actions), defaults (per-block behavioural defaults), limits (rate / quota caps), and requirements (cross-cutting must-haves like MFA / approval). Composable inline | ref | file. Granted on AIP-39 ACTION ids — implementations / TOOLs are decoupled from policy.",
5
+ "keywords": [
6
+ "agentproto",
7
+ "aip-38",
8
+ "policy",
9
+ "definePolicy",
10
+ "open-standard",
11
+ "agentic"
12
+ ],
13
+ "homepage": "https://agentproto.sh/docs/aip-38",
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "https://github.com/agentproto/ts",
17
+ "directory": "packages/policy"
18
+ },
19
+ "bugs": {
20
+ "url": "https://github.com/agentproto/ts/issues"
21
+ },
22
+ "license": "MIT",
23
+ "type": "module",
24
+ "main": "dist/index.mjs",
25
+ "module": "dist/index.mjs",
26
+ "types": "dist/index.d.ts",
27
+ "exports": {
28
+ ".": {
29
+ "types": "./dist/index.d.ts",
30
+ "import": "./dist/index.mjs",
31
+ "default": "./dist/index.mjs"
32
+ },
33
+ "./manifest": {
34
+ "types": "./dist/manifest/index.d.ts",
35
+ "import": "./dist/manifest/index.mjs",
36
+ "default": "./dist/manifest/index.mjs"
37
+ },
38
+ "./package.json": "./package.json"
39
+ },
40
+ "files": [
41
+ "dist",
42
+ "README.md",
43
+ "LICENSE"
44
+ ],
45
+ "publishConfig": {
46
+ "access": "public"
47
+ },
48
+ "dependencies": {
49
+ "gray-matter": "^4.0.3",
50
+ "zod": "^4.4.3",
51
+ "@agentproto/define-doctype": "0.1.0"
52
+ },
53
+ "devDependencies": {
54
+ "@types/node": "^25.6.2",
55
+ "tsup": "^8.5.1",
56
+ "typescript": "^5.9.3",
57
+ "vitest": "^3.2.4",
58
+ "@agentproto/tooling": "0.1.0-alpha.0"
59
+ },
60
+ "scripts": {
61
+ "dev": "tsup --watch",
62
+ "build": "tsup",
63
+ "clean": "rm -rf dist",
64
+ "check-types": "tsc --noEmit",
65
+ "test": "vitest run --passWithNoTests",
66
+ "test:watch": "vitest"
67
+ }
68
+ }