{"_id":"@arlopass/policy","name":"@arlopass/policy","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@arlopass/policy","version":"0.1.0","license":"MIT","type":"module","publishConfig":{"access":"public","provenance":true},"repository":{"type":"git","url":"git+https://github.com/arlopass/arlopass.git","directory":"packages/policy"},"homepage":"https://github.com/arlopass/arlopass/tree/main/packages/policy#readme","bugs":{"url":"https://github.com/arlopass/arlopass/issues"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"}},"main":"dist/index.js","types":"dist/index.d.ts","scripts":{"build":"tsc -p tsconfig.json","typecheck":"tsc -p tsconfig.json --noEmit","lint":"eslint \"src/**/*.ts\"","test":"vitest run --passWithNoTests"},"dependencies":{"@arlopass/protocol":"workspace:*"},"_id":"@arlopass/policy@0.1.0","gitHead":"524008c81190adecca51ec54fbe99d77ebdd056f","description":"Evaluate allow/deny rules against origins, capabilities, providers, and models. Policies are versioned, signed with Ed25519, and enforced at two points — preflight in the extension and runtime in the bridge.","_nodeVersion":"22.22.1","_npmVersion":"10.9.4","dist":{"integrity":"sha512-0/fjnttPmz8aZmLLvlULTHcBZ6SRLhUid7WeNHhKcoR0Y7sbhx7NLyQY0sUgQ4qxdntwCi3VgL5CNpMS+UEX9g==","shasum":"d3f4f15d1ca00695bb76d6bfa661ed69079129e1","tarball":"https://registry.npmjs.org/@arlopass/policy/-/policy-0.1.0.tgz","fileCount":26,"unpackedSize":108460,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@arlopass%2fpolicy@0.1.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIHr9Ys+6E8DVKJd8Jvo7QshPdjTKuk8SQWASFcb2eeX3AiEAs3oCQtQyA+POqtq8t1/focJFHrtG63JTe0cNWvlRBjE="}]},"_npmUser":{"name":"davidszakacs","email":"szakacs_david@hotmail.com"},"directories":{},"maintainers":[{"name":"davidszakacs","email":"szakacs_david@hotmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/policy_0.1.0_1774820857978_0.7908562567508073"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-29T21:47:37.847Z","0.1.0":"2026-03-29T21:47:38.114Z","modified":"2026-03-29T21:47:38.594Z"},"maintainers":[{"name":"davidszakacs","email":"szakacs_david@hotmail.com"}],"description":"Evaluate allow/deny rules against origins, capabilities, providers, and models. Policies are versioned, signed with Ed25519, and enforced at two points — preflight in the extension and runtime in the bridge.","homepage":"https://github.com/arlopass/arlopass/tree/main/packages/policy#readme","repository":{"type":"git","url":"git+https://github.com/arlopass/arlopass.git","directory":"packages/policy"},"bugs":{"url":"https://github.com/arlopass/arlopass/issues"},"license":"MIT","readme":"# @arlopass/policy\n\nEvaluate allow/deny rules against origins, capabilities, providers, and models. Policies are versioned, signed with Ed25519, and enforced at two points — preflight in the extension and runtime in the bridge.\n\n```ts\nimport { evaluatePolicy, parsePolicyBundle } from \"@arlopass/policy\";\n\nconst bundle = parsePolicyBundle({\n  schemaVersion: \"1.0.0\",\n  policyVersion: \"org.acme.v3\",\n  keyId: \"key-1\",\n  issuedAt: new Date().toISOString(),\n  rules: {\n    allowedOrigins: [\"https://app.acme.com\"],\n    deniedProviders: [\"untrusted-provider\"],\n  },\n});\n\nconst decision = evaluatePolicy({\n  origin: \"https://app.acme.com\",\n  capability: \"chat.completions\",\n  providerId: \"ollama\",\n  modelId: \"llama3.2\",\n  policyBundle: bundle,\n});\n\nconsole.log(decision.decision);   // \"allow\"\nconsole.log(decision.machineCode); // \"ARLOPASS_POLICY_ALLOW\"\n```\n\n---\n\n## API Reference\n\n### `evaluatePolicy(context: PolicyEvaluationContext, options?: PolicyEvaluationOptions): PolicyDecision`\n\nEvaluate a request against a policy bundle. Returns a decision with reason code and machine code.\n\n```ts\ntype PolicyDecision = {\n  decision: \"allow\" | \"deny\";\n  reasonCode: ProtocolReasonCode;\n  policyVersion: string;\n  machineCode: PolicyDecisionMachineCode;\n  correlationId?: string;\n}\n```\n\n---\n\n### Policy Bundle\n\n```ts\ntype PolicyBundle = {\n  schemaVersion: string;       // \"1.0.0\"\n  policyVersion: string;\n  keyId: string;\n  issuedAt: string;\n  expiresAt?: string;\n  rules: PolicyRuleSet;\n  metadata?: Record<string, string>;\n}\n```\n\n### Policy Rules\n\n```ts\ntype PolicyRuleSet = {\n  allowedOrigins?: readonly string[];\n  deniedOrigins?: readonly string[];\n  allowedCapabilities?: readonly ProtocolCapability[];\n  deniedCapabilities?: readonly ProtocolCapability[];\n  allowedProviders?: readonly string[];\n  deniedProviders?: readonly string[];\n  allowedModels?: readonly string[];\n  deniedModels?: readonly string[];\n}\n```\n\n### Signed Bundles\n\n```ts\ntype SignedPolicyBundle = {\n  payload: PolicyBundle;\n  signature: PolicyBundleSignature;\n}\n\ntype PolicyBundleSignature = {\n  algorithm: \"ed25519\";\n  keyId: string;\n  signedAt: string;\n  digest: string;\n  value: string;\n}\n```\n\n---\n\n### Parsing Functions\n\n| Function | Description |\n|----------|-------------|\n| `parsePolicyBundle(input: unknown): PolicyBundle` | Parse and validate a bundle, throws `PolicySchemaError` on failure |\n| `parseSignedPolicyBundle(input: unknown): SignedPolicyBundle` | Parse a signed bundle with signature |\n| `safeParsePolicyBundle(input: unknown): SafeParseResult<PolicyBundle>` | Returns `{ success, value/error }` |\n| `safeParseSignedPolicyBundle(input: unknown): SafeParseResult<SignedPolicyBundle>` | Non-throwing variant |\n| `isPolicyBundle(input: unknown): boolean` | Type guard |\n| `isSignedPolicyBundle(input: unknown): boolean` | Type guard |\n\n---\n\n### Signature Verification\n\n**`verifyPolicyBundleSignature(bundle: SignedPolicyBundle, options: { keyResolver: PolicyKeyResolver }): BundleVerificationResult`**\n\nVerify a signed bundle against a key resolver.\n\n**`canonicalizePolicyBundle(payload: PolicyBundle): string`** — Deterministic canonical form for signing.\n\n**`createPolicyBundleDigest(payload: PolicyBundle): string`** — Compute digest for the bundle payload.\n\n---\n\n### `InMemoryPolicyKeyManager`\n\nKey lifecycle manager for policy signing and verification.\n\n```ts\nimport { InMemoryPolicyKeyManager } from \"@arlopass/policy\";\n\nconst keys = new InMemoryPolicyKeyManager();\nconst key = keys.createKey({ algorithm: \"ed25519\" });\nconst rotated = keys.rotateKey(key.keyId, { algorithm: \"ed25519\" });\nkeys.revokeKey(rotated.previous.keyId, { reason: \"Scheduled rotation\" });\nconst pub = keys.resolvePublicKey(rotated.current.keyId);\n```\n\n| Method | Returns | Description |\n|--------|---------|-------------|\n| `createKey(input)` | `PolicyKeyRecord` | Generate a new Ed25519 key pair |\n| `rotateKey(keyId, input)` | `{ previous, current }` | Rotate a key, marking old as `rotated` |\n| `revokeKey(keyId, input?)` | `PolicyKeyRecord` | Revoke a key |\n| `getKey(keyId)` | `PolicyKeyRecord \\| undefined` | Look up a key by ID |\n| `listKeys()` | `readonly PolicyKeyRecord[]` | List all keys |\n| `resolvePublicKey(keyId, options?)` | `string \\| undefined` | Get PEM public key for verification |\n| `assertActiveKey(keyId)` | `PolicyKeyRecord` | Throws if key is not active |\n\n```ts\ntype PolicyKeyRecord = {\n  keyId: string;\n  publicKeyPem: string;\n  status: \"active\" | \"rotated\" | \"revoked\";\n  createdAt: string;\n  rotatedAt?: string;\n  revokedAt?: string;\n  replacementKeyId?: string;\n  revocationReason?: string;\n  metadata?: Record<string, string>;\n}\n```\n\n---\n\n### Decision Machine Codes (`POLICY_DECISION_MACHINE_CODES`)\n\n`ARLOPASS_POLICY_ALLOW` plus 16 deny variants: `DENY_POLICY_MISSING`, `DENY_POLICY_INVALID`, `DENY_ORIGIN_NOT_ALLOWED`, `DENY_ORIGIN_BLOCKED`, `DENY_CAPABILITY_NOT_ALLOWED`, `DENY_CAPABILITY_BLOCKED`, `DENY_PROVIDER_NOT_ALLOWED`, `DENY_PROVIDER_BLOCKED`, `DENY_MODEL_NOT_ALLOWED`, `DENY_MODEL_BLOCKED`, and others.\n\n**`toPolicyReasonCode(machineCode): ProtocolReasonCode`** — Map machine code to protocol reason code.\n\n**`isPolicyDecisionMachineCode(value: string): boolean`** — Type guard.\n\n---\n\n### Error Classes\n\n| Class | Description |\n|-------|-------------|\n| `PolicySchemaError` | Invalid bundle structure (has `code`, `field`, `details`) |\n| `PolicySignatureError` | Signature verification failure (has `code`) |\n| `PolicyKeyManagementError` | Key lifecycle error (has `code`, `keyId`, `details`) |\n\n---\n\n### Constants\n\n| Constant | Value |\n|----------|-------|\n| `POLICY_BUNDLE_SCHEMA_VERSION` | `\"1.0.0\"` |\n| `POLICY_SIGNATURE_ALGORITHM` | `\"ed25519\"` |\n\n### Dependencies\n\n- `@arlopass/protocol` — Capability types and reason codes\n","readmeFilename":"README.md","_rev":"1-377f84721d7d7b576631463d37b8dfd0"}