@tenuo/core 0.3.0-beta.0 → 0.3.2-beta.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/dist/wasm.js CHANGED
@@ -91,6 +91,18 @@ function throwIfGateError(error) {
91
91
  throw new TenuoConfigurationError(error);
92
92
  }
93
93
  }
94
+ /**
95
+ * Parse JSON text and reject a repeated key in any object.
96
+ *
97
+ * `verify()` receives an object the host already parsed. A duplicate key is
98
+ * gone by then. Call this while the text is still available. After the check,
99
+ * the value is `JSON.parse` of the original text, so each key is an own data
100
+ * property and `null` stays `null`.
101
+ */
102
+ export function parseStrictJson(text) {
103
+ loadWasm().parse_strict_json(text);
104
+ return JSON.parse(text);
105
+ }
94
106
  /**
95
107
  * Typed preflight of a warrant's approval gates for `(tool, args)`.
96
108
  *
package/dist/wasm.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"wasm.js","sourceRoot":"","sources":["../src/wasm.ts"],"names":[],"mappings":"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","sourcesContent":["import { createRequire } from \"node:module\";\nimport { existsSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { TenuoConfigurationError } from \"./errors.ts\";\nimport type { TenuoErrorCode } from \"./api.ts\";\n\nexport type WasmDecision = {\n outcome: \"allow\" | \"deny\" | \"approval_required\";\n code?: TenuoErrorCode;\n field?: string;\n message?: string;\n args?: Record<string, unknown>;\n tool?: string;\n required?: number;\n received?: number;\n receipt?: string;\n};\n\nexport type WasmInspect = {\n payload_hex: string;\n signature_hex: string;\n id: string;\n};\n\nexport type WasmReceipt = {\n authentic: true;\n /** Hex key the receipt is signed under — resolve against your authorizer set. */\n signer_key: string;\n outcome: \"allow\" | \"deny\";\n action: string;\n decision_code?: string;\n request_id: string;\n /** Version of the revocation list in force, when it carried one. */\n srl_version?: number;\n /**\n * SHA-256 (hex) of the revocation list bytes in force at decision time.\n * Absent means no revocation data was loaded — a different claim from a\n * loaded list that revoked nothing.\n */\n srl_hash?: string;\n /**\n * SHA-256 (hex) commitment to the canonical invocation this decision was\n * made over. Absent when the arguments could not be canonicalized — never\n * zero-filled, so absence is a claim rather than a value.\n */\n request_hash?: string;\n /** SHA-256 (hex) of the host ceiling applied to this decision. */\n policy_definition_hash?: string;\n /**\n * SHA-256 (hex) of the previous receipt from this signer. Absent on the\n * first receipt, or when the deployment does not chain. A broken link means\n * a receipt was removed from the stream.\n */\n prev_receipt_hash?: string;\n /** SHA-256 (hex) of the trusted root set in force at decision time. */\n trusted_roots_hash?: string;\n};\n\nexport type WasmReceiptChain = {\n signer_key: string;\n outcome: \"allow\" | \"deny\";\n decision_code?: string;\n timestamp: number;\n /** The embedded chain verifies to a supplied root at the decision instant. */\n chain_valid: boolean;\n /** Canonical error name when it does not. */\n chain_error?: string;\n /**\n * Deny receipts only: the chain failure matches the stated decision_code,\n * so the embedded authority independently corroborates the refusal.\n */\n corroborates_denial?: boolean;\n root_issuer?: string;\n leaf_holder?: string;\n};\n\nexport type WasmSession = object;\n\n/** Mirrors `SessionInfoDto` in tenuo-wasm. Snake case is the WASM boundary. */\nexport type WasmSessionInfo = {\n kind: \"execution\" | \"issuer\";\n holder_public_key: string;\n root_public_key: string;\n depth: number;\n max_depth: number;\n terminal: boolean;\n expires_at: number;\n tools: string[];\n warrant_ids: string[];\n can_authorize: boolean;\n clearance?: number;\n session_id?: string;\n agent_id?: string;\n issuable_tools?: string[];\n max_issue_depth?: number;\n required_approvers?: string[];\n min_approvals?: number;\n approval_gated_tools: string[];\n};\n\n/** Security limits exported by tenuo-core; TypeScript must not redefine them. */\nexport type WasmProtocolLimits = {\n max_delegation_depth: number;\n max_warrant_ttl_seconds: number;\n};\n\n/** Mirrors `NarrowOptions` in tenuo-wasm. Unknown keys are rejected there. */\nexport type WasmNarrowOptions = {\n holder?: string;\n ttlSeconds?: number;\n terminal?: boolean;\n maxDepth?: number;\n clearance?: number | string;\n agentId?: string;\n addApprovers?: string[];\n minApprovals?: number;\n};\n\nexport type WasmRequireApproval = {\n approvers: string[];\n min: number;\n tools?: string[];\n gates?: Record<string, { message?: string; args?: Record<string, unknown> }>;\n};\n\n/** Mirrors `MintOptions` in tenuo-wasm. */\nexport type WasmMintOptions = {\n kind?: \"execution\" | \"issuer\";\n allow?: unknown;\n ttlSeconds?: number;\n holder?: string;\n maxDepth?: number;\n clearance?: number | string;\n sessionId?: string;\n agentId?: string;\n requireApproval?: WasmRequireApproval;\n issuableTools?: string[];\n constraintBounds?: unknown;\n maxIssueDepth?: number;\n};\n\n/** Mirrors `IssueOptions` in tenuo-wasm. */\nexport type WasmIssueOptions = {\n allow: unknown;\n holder: string;\n ttlSeconds?: number;\n maxDepth?: number;\n clearance?: number | string;\n sessionId?: string;\n agentId?: string;\n requireApproval?: { approvers: string[]; min: number };\n};\n\nexport type WasmExplainField = {\n field: string;\n kind: string;\n constraint: unknown;\n value?: unknown;\n satisfied: boolean;\n reason?: string;\n};\n\nexport type WasmExplain = {\n tool: string;\n kind: \"execution\" | \"issuer\";\n outcome: \"allow\" | \"deny\";\n code?: TenuoErrorCode;\n field?: string;\n message?: string;\n tool_granted: boolean;\n fields: WasmExplainField[];\n unknown_fields: string[];\n missing_fields: string[];\n expired: boolean;\n expires_at: number;\n chain_valid: boolean;\n chain_error?: TenuoErrorCode;\n};\n\nexport type WasmApprovalRequest = {\n request_id: string;\n warrant_id: string;\n tool: string;\n args: Record<string, unknown>;\n request_hash: string;\n holder_public_key: string;\n required_approvers: string[];\n min_approvals: number;\n warrant_expires_at: number;\n created_at: number;\n message: string;\n};\n\nexport type WasmAttestation = {\n version: number;\n canonicalization: string;\n warrant_id: string;\n tool: string;\n request_hash: string;\n holder_key_hex: string;\n args_canonical_cbor_b64: string;\n signer_key_hex: string;\n signature_b64: string;\n};\n\nexport type WasmApprovalInfo = {\n approver_public_key: string;\n request_hash: string;\n external_id: string;\n approved_at: number;\n expires_at: number;\n expired: boolean;\n signature_valid: boolean;\n error?: string;\n};\n\nexport type WasmSrlInfo = {\n version: number;\n issued_at: number;\n issuer_public_key: string;\n revoked_ids: string[];\n signature_valid: boolean;\n};\n\nexport type WasmContext = {\n withReceiptSigner(secret: Uint8Array): WasmContext;\n mint(\n allow: unknown,\n ttlSeconds: number,\n requireApproval?: unknown,\n holderHex?: string,\n maxDepth?: number,\n ): WasmSession;\n mintExtended(options: WasmMintOptions): WasmSession;\n narrow(session: WasmSession, allow: unknown, options?: WasmNarrowOptions): WasmSession;\n issue(issuer: WasmSession, options: WasmIssueOptions): WasmSession;\n issuerPublicKey(): string;\n explain(session: WasmSession, tool: string, args: unknown): WasmExplain;\n approvalRequest(session: WasmSession, tool: string, args: unknown): WasmApprovalRequest;\n approvalContextAttestation(session: WasmSession, tool: string, args: unknown): WasmAttestation;\n signRevocationListVersioned(ids: string[], version?: number): string;\n authorize(\n session: WasmSession,\n tool: string,\n args: unknown,\n approvals?: unknown,\n toolAllow?: unknown,\n requestId?: string,\n ): WasmDecision;\n authorizeAsOf(\n session: WasmSession,\n tool: string,\n args: unknown,\n asOf: number,\n approvals?: unknown,\n toolAllow?: unknown,\n ): WasmDecision;\n loadRevocationList(srl: string): void;\n signRevocationList(ids: string[]): string;\n signPop(session: WasmSession, tool: string, args: unknown): string;\n authorizePresented(\n warrants: unknown,\n tool: string,\n args: unknown,\n pop: string,\n approvals?: unknown,\n toolAllow?: unknown,\n requestId?: string,\n ): WasmDecision;\n};\n\ntype Generated = {\n SdkContext: {\n new (): WasmContext;\n fromTrustedRoots(roots: string[]): WasmContext;\n fromIssuerSecret(secret: Uint8Array, extraRoots?: string[]): WasmContext;\n };\n SdkSession: {\n fromWire(warrant: string, holder: Uint8Array): WasmSession;\n fromParts(payloadHex: string, signatureHex: string, holder: Uint8Array): WasmSession;\n fromChain(parts: unknown, holder: Uint8Array): WasmSession;\n };\n sdkInspectWarrant(wire: string): WasmInspect;\n sdkInspectParts(payloadHex: string, signatureHex: string): WasmInspect;\n sdkProtocolLimits(): WasmProtocolLimits;\n sdkPublicKeyFromHolderKey(holderSecret: Uint8Array): string;\n sdkSignApproval(\n session: WasmSession,\n tool: string,\n args: unknown,\n approverSecret: Uint8Array,\n externalId: string,\n asOf?: number,\n ): string;\n sdkSignApprovalForRequest(\n requestHashHex: string,\n approverSecret: Uint8Array,\n externalId: string,\n ttlSeconds?: number,\n warrantExpiresAt?: number,\n ): string;\n sdkInspectApproval(envelope: string): WasmApprovalInfo;\n sdkSignRevocationList(ids: string[], issuerSecret: Uint8Array): string;\n sdkSignRevocationListVersioned(ids: string[], version: number | undefined, issuerSecret: Uint8Array): string;\n sdkSignPublishedRevocationList(ids: string[], version: number, issuerSecret: Uint8Array): string;\n sdkInspectRevocationList(wire: string): WasmSrlInfo;\n sdkVerifyReceipt(wire: string): WasmReceipt;\n sdkVerifyReceiptChain(wire: string, roots: string[]): WasmReceiptChain;\n approval_requirement(\n warrantB64: string,\n tool: string,\n args: unknown,\n ): ApprovalRequirement & { error?: string };\n inspect_approval_gate(\n warrantB64: string,\n tool: string,\n ): ApprovalGateInspection & { error?: string };\n evaluate_approval_gates(\n warrantB64: string,\n tool: string,\n args: unknown,\n ): { approval_required: boolean; tool: string; error?: string };\n};\n\nlet loaded: Generated | undefined;\n\nfunction generatedPath(): string {\n const here = dirname(fileURLToPath(import.meta.url));\n return join(here, \"generated\", \"tenuo_wasm.js\");\n}\n\nexport function wasmAvailable(): boolean {\n return existsSync(generatedPath());\n}\n\nconst WASM_LOAD_HINT =\n \"WASM core is missing from this @tenuo/core install. @tenuo/core is Node 20+ only (not a bundler target). If this is Next.js/webpack, set serverExternalPackages: ['@tenuo/core']. Do not run wasm-pack in the consuming app.\";\n\nexport function loadWasm(): Generated {\n if (loaded) {\n return loaded;\n }\n const path = generatedPath();\n if (!existsSync(path)) {\n throw new TenuoConfigurationError(WASM_LOAD_HINT, \"TENUO_NOT_READY\");\n }\n try {\n const require = createRequire(import.meta.url);\n loaded = require(path) as Generated;\n return loaded;\n } catch (error) {\n const wrapped = new TenuoConfigurationError(WASM_LOAD_HINT, \"TENUO_NOT_READY\");\n wrapped.cause = error;\n throw wrapped;\n }\n}\n\nexport function createDevContext(receiptSigner?: Uint8Array): WasmContext {\n const { SdkContext } = loadWasm();\n let context: WasmContext = new SdkContext();\n if (receiptSigner !== undefined) {\n context = context.withReceiptSigner(receiptSigner);\n }\n return context;\n}\n\nexport function protocolLimits(): WasmProtocolLimits {\n return loadWasm().sdkProtocolLimits();\n}\n\nexport function createVerifierContext(\n rootHexes: readonly string[],\n revocationList?: string,\n receiptSigner?: Uint8Array,\n): WasmContext {\n const { SdkContext } = loadWasm();\n let context = SdkContext.fromTrustedRoots([...rootHexes]);\n if (receiptSigner !== undefined) {\n context = context.withReceiptSigner(receiptSigner);\n }\n if (revocationList !== undefined && revocationList.length > 0) {\n context.loadRevocationList(revocationList);\n }\n return context;\n}\n\nexport function createIssuerContext(\n secret: Uint8Array,\n extraRootHexes: readonly string[],\n receiptSigner?: Uint8Array,\n): WasmContext {\n const { SdkContext } = loadWasm();\n let context = SdkContext.fromIssuerSecret(secret, [...extraRootHexes]);\n if (receiptSigner !== undefined) {\n context = context.withReceiptSigner(receiptSigner);\n }\n return context;\n}\n\nexport function importSessionFromWire(warrant: string, holderKey: Uint8Array): WasmSession {\n const { SdkSession } = loadWasm();\n return SdkSession.fromWire(warrant, holderKey);\n}\n\nexport function importSessionFromParts(\n payloadHex: string,\n signatureHex: string,\n holderKey: Uint8Array,\n): WasmSession {\n const { SdkSession } = loadWasm();\n return SdkSession.fromParts(payloadHex, signatureHex, holderKey);\n}\n\nexport function importSessionFromChain(parts: unknown, holderKey: Uint8Array): WasmSession {\n const { SdkSession } = loadWasm();\n return SdkSession.fromChain(parts, holderKey);\n}\n\nexport function inspectWarrant(wire: string): WasmInspect {\n return loadWasm().sdkInspectWarrant(wire);\n}\n\nexport function inspectParts(payloadHex: string, signatureHex: string): WasmInspect {\n return loadWasm().sdkInspectParts(payloadHex, signatureHex);\n}\n\n/** Hex public key for a 32-byte holder secret. Ed25519, derived in Rust. */\nexport function publicKeyHexFromHolderKey(holderSecret: Uint8Array): string {\n return loadWasm().sdkPublicKeyFromHolderKey(holderSecret);\n}\n\nexport type ApprovalRequirementStatus = \"not_gated\" | \"exempt\" | \"required\" | \"denied\";\n\nexport type ApprovalRequirement = {\n status: ApprovalRequirementStatus;\n tool: string;\n kind?: \"whole_tool\" | \"argument\";\n argument?: string;\n arguments: string[];\n message?: string;\n code?: string;\n reason?: string;\n};\n\nexport type ApprovalGateInspection = {\n kind: \"none\" | \"whole_tool\" | \"conditional\" | \"unknown\";\n tool: string;\n arguments: string[];\n message?: string;\n};\n\nfunction loadApprovalWasm() {\n return loadWasm();\n}\n\nfunction throwIfGateError(error: string | undefined): void {\n if (error) {\n throw new TenuoConfigurationError(error);\n }\n}\n\n/**\n * Typed preflight of a warrant's approval gates for `(tool, args)`.\n *\n * Capability constraints are checked first. `denied` means the authorizer\n * will refuse the call — do not collect approval. Malformed encodings throw\n * (fail-closed).\n */\nexport function approvalRequirement(\n warrantB64: string,\n tool: string,\n args: Record<string, unknown>,\n): ApprovalRequirement {\n const result = loadApprovalWasm().approval_requirement(warrantB64, tool, args);\n throwIfGateError(result.error);\n return result;\n}\n\n/** Inspect how a warrant gates `tool`, without evaluating arguments. */\nexport function inspectApprovalGate(warrantB64: string, tool: string): ApprovalGateInspection {\n const result = loadApprovalWasm().inspect_approval_gate(warrantB64, tool);\n throwIfGateError(result.error);\n return result;\n}\n\n/**\n * Gate-map-only boolean. Does not run capability checks, so split-view\n * callers (PoP args vs constraint args) still see a firing gate. Prefer\n * {@link approvalRequirement} when the caller must distinguish `denied`.\n */\nexport function evaluateApprovalGates(\n warrantB64: string,\n tool: string,\n args: Record<string, unknown>,\n): boolean {\n const result = loadApprovalWasm().evaluate_approval_gates(warrantB64, tool, args);\n throwIfGateError(result.error);\n return result.approval_required;\n}\n"]}
1
+ {"version":3,"file":"wasm.js","sourceRoot":"","sources":["../src/wasm.ts"],"names":[],"mappings":"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","sourcesContent":["import { createRequire } from \"node:module\";\nimport { existsSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { TenuoConfigurationError } from \"./errors.ts\";\nimport type { TenuoErrorCode } from \"./api.ts\";\n\nexport type WasmDecision = {\n outcome: \"allow\" | \"deny\" | \"approval_required\";\n code?: TenuoErrorCode;\n field?: string;\n message?: string;\n args?: Record<string, unknown>;\n tool?: string;\n required?: number;\n received?: number;\n receipt?: string;\n};\n\nexport type WasmInspect = {\n payload_hex: string;\n signature_hex: string;\n id: string;\n};\n\nexport type WasmReceipt = {\n authentic: true;\n /** Hex key the receipt is signed under — resolve against your authorizer set. */\n signer_key: string;\n outcome: \"allow\" | \"deny\";\n action: string;\n decision_code?: string;\n request_id: string;\n /** Version of the revocation list in force, when it carried one. */\n srl_version?: number;\n /**\n * SHA-256 (hex) of the revocation list bytes in force at decision time.\n * Absent means no revocation data was loaded — a different claim from a\n * loaded list that revoked nothing.\n */\n srl_hash?: string;\n /**\n * SHA-256 (hex) commitment to the canonical invocation this decision was\n * made over. Absent when the arguments could not be canonicalized — never\n * zero-filled, so absence is a claim rather than a value.\n */\n request_hash?: string;\n /** SHA-256 (hex) of the host ceiling applied to this decision. */\n policy_definition_hash?: string;\n /**\n * SHA-256 (hex) of the previous receipt from this signer. Absent on the\n * first receipt, or when the deployment does not chain. A broken link means\n * a receipt was removed from the stream.\n */\n prev_receipt_hash?: string;\n /** SHA-256 (hex) of the trusted root set in force at decision time. */\n trusted_roots_hash?: string;\n};\n\nexport type WasmReceiptChain = {\n signer_key: string;\n outcome: \"allow\" | \"deny\";\n decision_code?: string;\n timestamp: number;\n /** The embedded chain verifies to a supplied root at the decision instant. */\n chain_valid: boolean;\n /** Canonical error name when it does not. */\n chain_error?: string;\n /**\n * Deny receipts only: the chain failure matches the stated decision_code,\n * so the embedded authority independently corroborates the refusal.\n */\n corroborates_denial?: boolean;\n root_issuer?: string;\n leaf_holder?: string;\n};\n\nexport type WasmSession = object;\n\n/** Mirrors `SessionInfoDto` in tenuo-wasm. Snake case is the WASM boundary. */\nexport type WasmSessionInfo = {\n kind: \"execution\" | \"issuer\";\n holder_public_key: string;\n root_public_key: string;\n depth: number;\n max_depth: number;\n terminal: boolean;\n expires_at: number;\n tools: string[];\n warrant_ids: string[];\n can_authorize: boolean;\n clearance?: number;\n session_id?: string;\n agent_id?: string;\n issuable_tools?: string[];\n max_issue_depth?: number;\n required_approvers?: string[];\n min_approvals?: number;\n approval_gated_tools: string[];\n};\n\n/** Security limits exported by tenuo-core; TypeScript must not redefine them. */\nexport type WasmProtocolLimits = {\n max_delegation_depth: number;\n max_warrant_ttl_seconds: number;\n};\n\n/** Mirrors `NarrowOptions` in tenuo-wasm. Unknown keys are rejected there. */\nexport type WasmNarrowOptions = {\n holder?: string;\n ttlSeconds?: number;\n terminal?: boolean;\n maxDepth?: number;\n clearance?: number | string;\n agentId?: string;\n addApprovers?: string[];\n minApprovals?: number;\n};\n\nexport type WasmRequireApproval = {\n approvers: string[];\n min: number;\n tools?: string[];\n gates?: Record<string, { message?: string; args?: Record<string, unknown> }>;\n};\n\n/** Mirrors `MintOptions` in tenuo-wasm. */\nexport type WasmMintOptions = {\n kind?: \"execution\" | \"issuer\";\n allow?: unknown;\n ttlSeconds?: number;\n holder?: string;\n maxDepth?: number;\n clearance?: number | string;\n sessionId?: string;\n agentId?: string;\n requireApproval?: WasmRequireApproval;\n issuableTools?: string[];\n constraintBounds?: unknown;\n maxIssueDepth?: number;\n};\n\n/** Mirrors `IssueOptions` in tenuo-wasm. */\nexport type WasmIssueOptions = {\n allow: unknown;\n holder: string;\n ttlSeconds?: number;\n maxDepth?: number;\n clearance?: number | string;\n sessionId?: string;\n agentId?: string;\n requireApproval?: { approvers: string[]; min: number };\n};\n\nexport type WasmExplainField = {\n field: string;\n kind: string;\n constraint: unknown;\n value?: unknown;\n satisfied: boolean;\n reason_code?: string;\n reason?: string;\n};\n\nexport type WasmExplain = {\n tool: string;\n kind: \"execution\" | \"issuer\";\n outcome: \"allow\" | \"deny\";\n code?: TenuoErrorCode;\n field?: string;\n message?: string;\n tool_granted: boolean;\n fields: WasmExplainField[];\n unknown_fields: string[];\n missing_fields: string[];\n expired: boolean;\n expires_at: number;\n chain_valid: boolean;\n chain_error?: TenuoErrorCode;\n};\n\nexport type WasmApprovalRequest = {\n request_id: string;\n warrant_id: string;\n tool: string;\n args: Record<string, unknown>;\n request_hash: string;\n holder_public_key: string;\n required_approvers: string[];\n min_approvals: number;\n warrant_expires_at: number;\n created_at: number;\n message: string;\n};\n\nexport type WasmAttestation = {\n version: number;\n canonicalization: string;\n warrant_id: string;\n tool: string;\n request_hash: string;\n holder_key_hex: string;\n args_canonical_cbor_b64: string;\n signer_key_hex: string;\n signature_b64: string;\n};\n\nexport type WasmApprovalInfo = {\n approver_public_key: string;\n request_hash: string;\n external_id: string;\n approved_at: number;\n expires_at: number;\n expired: boolean;\n signature_valid: boolean;\n error?: string;\n};\n\nexport type WasmSrlInfo = {\n version: number;\n issued_at: number;\n issuer_public_key: string;\n revoked_ids: string[];\n signature_valid: boolean;\n};\n\nexport type WasmContext = {\n withReceiptSigner(secret: Uint8Array): WasmContext;\n mint(\n allow: unknown,\n ttlSeconds: number,\n requireApproval?: unknown,\n holderHex?: string,\n maxDepth?: number,\n ): WasmSession;\n mintExtended(options: WasmMintOptions): WasmSession;\n narrow(session: WasmSession, allow: unknown, options?: WasmNarrowOptions): WasmSession;\n issue(issuer: WasmSession, options: WasmIssueOptions): WasmSession;\n issuerPublicKey(): string;\n explain(session: WasmSession, tool: string, args: unknown): WasmExplain;\n approvalRequest(session: WasmSession, tool: string, args: unknown): WasmApprovalRequest;\n approvalContextAttestation(session: WasmSession, tool: string, args: unknown): WasmAttestation;\n signRevocationListVersioned(ids: string[], version?: number): string;\n authorize(\n session: WasmSession,\n tool: string,\n args: unknown,\n approvals?: unknown,\n toolAllow?: unknown,\n requestId?: string,\n ): WasmDecision;\n authorizeAsOf(\n session: WasmSession,\n tool: string,\n args: unknown,\n asOf: number,\n approvals?: unknown,\n toolAllow?: unknown,\n ): WasmDecision;\n loadRevocationList(srl: string): void;\n signRevocationList(ids: string[]): string;\n signPop(session: WasmSession, tool: string, args: unknown): string;\n signMeta(\n session: WasmSession,\n tool: string,\n argsJson: string,\n timestamp: number,\n approvals?: unknown,\n ): { warrant: string; signature: string; approvals?: string[] };\n /** Holder proof only; does not authorize execution. */\n verifyMetaPop(\n warrant: string,\n signature: string,\n tool: string,\n argsJson: string,\n timestamp: number,\n ): boolean;\n /** Compatibility alias for verifyMetaPop. */\n verifyMeta(\n warrant: string,\n signature: string,\n tool: string,\n argsJson: string,\n timestamp: number,\n ): boolean;\n authorizePresented(\n warrants: unknown,\n tool: string,\n args: unknown,\n pop: string,\n approvals?: unknown,\n toolAllow?: unknown,\n requestId?: string,\n ): WasmDecision;\n};\n\ntype Generated = {\n SdkContext: {\n new (): WasmContext;\n fromTrustedRoots(roots: string[]): WasmContext;\n fromIssuerSecret(secret: Uint8Array, extraRoots?: string[]): WasmContext;\n };\n SdkSession: {\n fromWire(warrant: string, holder: Uint8Array): WasmSession;\n fromParts(payloadHex: string, signatureHex: string, holder: Uint8Array): WasmSession;\n fromChain(parts: unknown, holder: Uint8Array): WasmSession;\n };\n sdkInspectWarrant(wire: string): WasmInspect;\n sdkInspectParts(payloadHex: string, signatureHex: string): WasmInspect;\n sdkProtocolLimits(): WasmProtocolLimits;\n sdkPublicKeyFromHolderKey(holderSecret: Uint8Array): string;\n sdkSignApproval(\n session: WasmSession,\n tool: string,\n args: unknown,\n approverSecret: Uint8Array,\n externalId: string,\n asOf?: number,\n ): string;\n sdkSignApprovalForRequest(\n requestHashHex: string,\n approverSecret: Uint8Array,\n externalId: string,\n ttlSeconds?: number,\n warrantExpiresAt?: number,\n ): string;\n sdkInspectApproval(envelope: string): WasmApprovalInfo;\n sdkSignRevocationList(ids: string[], issuerSecret: Uint8Array): string;\n sdkSignRevocationListVersioned(ids: string[], version: number | undefined, issuerSecret: Uint8Array): string;\n sdkSignPublishedRevocationList(ids: string[], version: number, issuerSecret: Uint8Array): string;\n sdkInspectRevocationList(wire: string): WasmSrlInfo;\n sdkVerifyReceipt(wire: string): WasmReceipt;\n sdkVerifyReceiptChain(wire: string, roots: string[]): WasmReceiptChain;\n approval_requirement(\n warrantB64: string,\n tool: string,\n args: unknown,\n ): ApprovalRequirement & { error?: string };\n inspect_approval_gate(\n warrantB64: string,\n tool: string,\n ): ApprovalGateInspection & { error?: string };\n evaluate_approval_gates(\n warrantB64: string,\n tool: string,\n args: unknown,\n ): { approval_required: boolean; tool: string; error?: string };\n parse_strict_json(jsonText: string): void;\n};\n\nlet loaded: Generated | undefined;\n\nfunction generatedPath(): string {\n const here = dirname(fileURLToPath(import.meta.url));\n return join(here, \"generated\", \"tenuo_wasm.js\");\n}\n\nexport function wasmAvailable(): boolean {\n return existsSync(generatedPath());\n}\n\nconst WASM_LOAD_HINT =\n \"WASM core is missing from this @tenuo/core install. @tenuo/core is Node 20+ only (not a bundler target). If this is Next.js/webpack, set serverExternalPackages: ['@tenuo/core']. Do not run wasm-pack in the consuming app.\";\n\nexport function loadWasm(): Generated {\n if (loaded) {\n return loaded;\n }\n const path = generatedPath();\n if (!existsSync(path)) {\n throw new TenuoConfigurationError(WASM_LOAD_HINT, \"TENUO_NOT_READY\");\n }\n try {\n const require = createRequire(import.meta.url);\n loaded = require(path) as Generated;\n return loaded;\n } catch (error) {\n const wrapped = new TenuoConfigurationError(WASM_LOAD_HINT, \"TENUO_NOT_READY\");\n wrapped.cause = error;\n throw wrapped;\n }\n}\n\nexport function createDevContext(receiptSigner?: Uint8Array): WasmContext {\n const { SdkContext } = loadWasm();\n let context: WasmContext = new SdkContext();\n if (receiptSigner !== undefined) {\n context = context.withReceiptSigner(receiptSigner);\n }\n return context;\n}\n\nexport function protocolLimits(): WasmProtocolLimits {\n return loadWasm().sdkProtocolLimits();\n}\n\nexport function createVerifierContext(\n rootHexes: readonly string[],\n revocationList?: string,\n receiptSigner?: Uint8Array,\n): WasmContext {\n const { SdkContext } = loadWasm();\n let context = SdkContext.fromTrustedRoots([...rootHexes]);\n if (receiptSigner !== undefined) {\n context = context.withReceiptSigner(receiptSigner);\n }\n if (revocationList !== undefined && revocationList.length > 0) {\n context.loadRevocationList(revocationList);\n }\n return context;\n}\n\nexport function createIssuerContext(\n secret: Uint8Array,\n extraRootHexes: readonly string[],\n receiptSigner?: Uint8Array,\n): WasmContext {\n const { SdkContext } = loadWasm();\n let context = SdkContext.fromIssuerSecret(secret, [...extraRootHexes]);\n if (receiptSigner !== undefined) {\n context = context.withReceiptSigner(receiptSigner);\n }\n return context;\n}\n\nexport function importSessionFromWire(warrant: string, holderKey: Uint8Array): WasmSession {\n const { SdkSession } = loadWasm();\n return SdkSession.fromWire(warrant, holderKey);\n}\n\nexport function importSessionFromParts(\n payloadHex: string,\n signatureHex: string,\n holderKey: Uint8Array,\n): WasmSession {\n const { SdkSession } = loadWasm();\n return SdkSession.fromParts(payloadHex, signatureHex, holderKey);\n}\n\nexport function importSessionFromChain(parts: unknown, holderKey: Uint8Array): WasmSession {\n const { SdkSession } = loadWasm();\n return SdkSession.fromChain(parts, holderKey);\n}\n\nexport function inspectWarrant(wire: string): WasmInspect {\n return loadWasm().sdkInspectWarrant(wire);\n}\n\nexport function inspectParts(payloadHex: string, signatureHex: string): WasmInspect {\n return loadWasm().sdkInspectParts(payloadHex, signatureHex);\n}\n\n/** Hex public key for a 32-byte holder secret. Ed25519, derived in Rust. */\nexport function publicKeyHexFromHolderKey(holderSecret: Uint8Array): string {\n return loadWasm().sdkPublicKeyFromHolderKey(holderSecret);\n}\n\nexport type ApprovalRequirementStatus = \"not_gated\" | \"exempt\" | \"required\" | \"denied\";\n\nexport type ApprovalRequirement = {\n status: ApprovalRequirementStatus;\n tool: string;\n kind?: \"whole_tool\" | \"argument\";\n argument?: string;\n arguments: string[];\n message?: string;\n code?: string;\n reason?: string;\n};\n\nexport type ApprovalGateInspection = {\n kind: \"none\" | \"whole_tool\" | \"conditional\" | \"unknown\";\n tool: string;\n arguments: string[];\n message?: string;\n};\n\nfunction loadApprovalWasm() {\n return loadWasm();\n}\n\nfunction throwIfGateError(error: string | undefined): void {\n if (error) {\n throw new TenuoConfigurationError(error);\n }\n}\n\n/**\n * Parse JSON text and reject a repeated key in any object.\n *\n * `verify()` receives an object the host already parsed. A duplicate key is\n * gone by then. Call this while the text is still available. After the check,\n * the value is `JSON.parse` of the original text, so each key is an own data\n * property and `null` stays `null`.\n */\nexport function parseStrictJson(text: string): unknown {\n loadWasm().parse_strict_json(text);\n return JSON.parse(text);\n}\n\n/**\n * Typed preflight of a warrant's approval gates for `(tool, args)`.\n *\n * Capability constraints are checked first. `denied` means the authorizer\n * will refuse the call — do not collect approval. Malformed encodings throw\n * (fail-closed).\n */\nexport function approvalRequirement(\n warrantB64: string,\n tool: string,\n args: Record<string, unknown>,\n): ApprovalRequirement {\n const result = loadApprovalWasm().approval_requirement(warrantB64, tool, args);\n throwIfGateError(result.error);\n return result;\n}\n\n/** Inspect how a warrant gates `tool`, without evaluating arguments. */\nexport function inspectApprovalGate(warrantB64: string, tool: string): ApprovalGateInspection {\n const result = loadApprovalWasm().inspect_approval_gate(warrantB64, tool);\n throwIfGateError(result.error);\n return result;\n}\n\n/**\n * Gate-map-only boolean. Does not run capability checks, so split-view\n * callers (PoP args vs constraint args) still see a firing gate. Prefer\n * {@link approvalRequirement} when the caller must distinguish `denied`.\n */\nexport function evaluateApprovalGates(\n warrantB64: string,\n tool: string,\n args: Record<string, unknown>,\n): boolean {\n const result = loadApprovalWasm().evaluate_approval_gates(warrantB64, tool, args);\n throwIfGateError(result.error);\n return result.approval_required;\n}\n"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tenuo/core",
3
- "version": "0.3.0-beta.0",
4
- "description": "Tenuo TypeScript SDK — authorization decisions run in the Rust core (WASM).",
3
+ "version": "0.3.2-beta.0",
4
+ "description": "Task-scoped authorization for AI agents in TypeScript: signed warrants limit which tools an agent can call and with which arguments, verified by the Tenuo Rust core compiled to WASM (beta).",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Tenuo Contributors",
7
7
  "homepage": "https://github.com/tenuo-ai/tenuo/tree/main/tenuo-ts/packages/core",
@@ -16,10 +16,17 @@
16
16
  "keywords": [
17
17
  "tenuo",
18
18
  "authorization",
19
- "agents",
19
+ "ai-agents",
20
+ "agent-security",
21
+ "llm-security",
22
+ "access-control",
23
+ "capabilities",
24
+ "warrants",
25
+ "delegation",
26
+ "prompt-injection",
20
27
  "mcp",
21
- "wasm",
22
- "capabilities"
28
+ "model-context-protocol",
29
+ "wasm"
23
30
  ],
24
31
  "publishConfig": {
25
32
  "access": "public"
@@ -46,7 +53,7 @@
46
53
  "test": "vitest run",
47
54
  "test:watch": "vitest",
48
55
  "typecheck": "tsc --noEmit",
49
- "build": "tsc -p tsconfig.build.json && node scripts/copy-build-assets.mjs",
56
+ "build": "tsc -p tsconfig.build.json && node scripts/copy-build-assets.mjs && node scripts/write-build-info.mjs",
50
57
  "pack:smoke": "node scripts/pack-smoke.mjs",
51
58
  "publish:npm": "npm publish --access public --provenance --tag beta",
52
59
  "build:wasm": "pnpm --dir ../.. build:wasm"