@arnilo/prism 0.0.12 → 0.0.13
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/CHANGELOG.md +11 -0
- package/dist/agents.js +21 -2
- package/dist/contracts.d.ts +25 -1
- package/dist/extensions.d.ts +11 -0
- package/dist/extensions.js +15 -0
- package/dist/identity.d.ts +92 -0
- package/dist/identity.js +257 -0
- package/dist/index.d.ts +6 -2
- package/dist/index.js +3 -1
- package/dist/persistence-lifecycle.d.ts +103 -0
- package/dist/persistence-lifecycle.js +204 -0
- package/dist/providers/openai-compatible.d.ts +5 -1
- package/dist/providers/openai-compatible.js +15 -6
- package/dist/secure-agent.js +7 -1
- package/dist/testing/persistence-schema.d.ts +2 -2
- package/dist/testing/persistence-schema.js +35 -2
- package/dist/tools.d.ts +2 -0
- package/dist/tools.js +6 -0
- package/docs/a2a.md +2 -0
- package/docs/agent-identity.md +111 -0
- package/docs/credential-storage.md +3 -0
- package/docs/database-persistence.md +18 -7
- package/docs/extensions.md +1 -0
- package/docs/guardrails.md +3 -0
- package/docs/host-security.md +5 -1
- package/docs/index.md +17 -8
- package/docs/mcp-tools.md +2 -0
- package/docs/migration.md +27 -0
- package/docs/model-routing.md +102 -0
- package/docs/observability.md +2 -0
- package/docs/performance.md +19 -0
- package/docs/policy-and-audit.md +127 -0
- package/docs/postgres-persistence.md +1 -1
- package/docs/provider-packages.md +8 -1
- package/docs/provider-request-policies.md +2 -0
- package/docs/providers/azure.md +74 -0
- package/docs/providers/bedrock.md +72 -0
- package/docs/providers/google.md +1 -0
- package/docs/providers/openai-compatible.md +3 -1
- package/docs/providers/openrouter.md +2 -0
- package/docs/providers/vertex.md +71 -0
- package/docs/public-contracts.md +3 -1
- package/docs/release-and-install.md +78 -6
- package/docs/review-coverage-2026-07-23-phase-8.md +245 -0
- package/docs/runs-and-usage.md +2 -0
- package/docs/server.md +33 -4
- package/docs/sqlite-persistence.md +1 -1
- package/docs/supervisors.md +2 -0
- package/docs/work-connectors.md +28 -0
- package/docs/work-tools.md +114 -0
- package/package.json +4 -1
|
@@ -206,6 +206,7 @@ const providers = createOpenAIProviderPackage({ apiKey });
|
|
|
206
206
|
- Keychain `list()` / `listOAuth()` are intentionally unsupported — enumerate credentials through host configuration instead of scanning the OS store.
|
|
207
207
|
- Combine with `createExplicitCredentialResolver()` so runtime overrides still win over stored values.
|
|
208
208
|
- Wire `createOAuthCredentialStoreAdapter(store)` into `refreshOAuthCredential()` only for an OAuth flow explicitly selected by the host and authorized by that provider. In 0.0.12 that means OpenAI Codex; Anthropic and Google packages accept API keys only. Never import or migrate Claude Code/Gemini CLI credential files, setup tokens, browser sessions, or CLI OAuth rows into this store.
|
|
209
|
+
- Enterprise cloud providers (`azure` / `bedrock` / `vertex`) expect host workload-identity callbacks (Entra / IAM / ADC), not this local encrypted/keychain store as a cloud token minting service. Store may hold opaque refresh material only when the host already owns the cloud auth flow.
|
|
209
210
|
|
|
210
211
|
## Security and performance notes
|
|
211
212
|
|
|
@@ -216,6 +217,7 @@ const providers = createOpenAIProviderPackage({ apiKey });
|
|
|
216
217
|
- Keychain operations use `@napi-rs/keyring`'s abort-aware `AsyncEntry`, so native work runs outside the JavaScript event loop. A main-loop timer aborts and rejects at `timeoutMs`; native cancellation remains OS/backend-dependent and may briefly retain one libuv worker after rejection.
|
|
217
218
|
- Keychain payloads are bytes rather than password strings and are zeroed after parse/write. Unknown native errors are mapped to sanitized typed errors; no native message or secret value is echoed.
|
|
218
219
|
- Never log passphrases, derived keys, or decrypted credential payloads.
|
|
220
|
+
- Optional host KMS: `encryptWithHostKms` / `decryptWithHostKms` wrap a random AES-256-GCM DEK via host `HostKms.wrapKey`/`unwrapKey` (timeout ≤ 60 s). Envelope sizes reuse vault/file caps. Keys are never logged. `createMemoryHostKms` is for tests only.
|
|
219
221
|
- Storage is not OAuth eligibility. A durable store may persist credentials for a provider only after the host selects a provider-authorized flow; it must not be used to piggyback on a vendor CLI or consumer subscription.
|
|
220
222
|
- Live keychain tests are opt-in (`PRISM_TEST_KEYCHAIN=1`); default `npm test` stays offline.
|
|
221
223
|
|
|
@@ -230,6 +232,7 @@ MCP credentials remain host inputs: resolve them before constructing client `req
|
|
|
230
232
|
## Related APIs
|
|
231
233
|
|
|
232
234
|
- [Credentials and redaction](credentials-and-redaction.md): core resolver helpers and `refreshOAuthCredential()`
|
|
235
|
+
- [Azure OpenAI / Foundry](providers/azure.md) / [Amazon Bedrock](providers/bedrock.md) / [Google Vertex AI](providers/vertex.md): enterprise workload-identity credential callbacks
|
|
233
236
|
- [Web search, fetch, and extraction](web-tools.md): late-bound Brave/Exa/Firecrawl credentials
|
|
234
237
|
- [Security/auth/trust](settings-auth-trust-security.md): host-owned settings/credentials boundaries
|
|
235
238
|
- [Persistence, credentials, and multimodality primitives](persistence-credentials-multimodality-primitives.md): Plan 056 threat model and conformance matrix rows 7–10
|
|
@@ -334,19 +334,30 @@ Use `cursor`/`limit` when an adapter pages very long branches. Do not implement
|
|
|
334
334
|
|
|
335
335
|
## Retention policies
|
|
336
336
|
|
|
337
|
-
A retention policy is a host-managed rule attached to sessions via `retention_policy_id`.
|
|
337
|
+
A retention policy is a host-managed rule attached to sessions via `retention_policy_id`. Phase 8 adds optional `ProductionPersistenceStore.lifecycle` (`createMemoryPersistenceLifecycle`, SQLite/Postgres `persistence.lifecycle`) for bounded apply/hold/export/quota:
|
|
338
|
+
|
|
339
|
+
```ts
|
|
340
|
+
await store.lifecycle.putLegalHold({ tenantId, userId, resourceKind: "session", resourceId, reason });
|
|
341
|
+
await store.lifecycle.applyRetention({ tenantId, userId, policy, candidates }); // hold wins over delete
|
|
342
|
+
await store.lifecycle.exportUnderHold({ tenantId, userId, cursor, limit }); // redacted
|
|
343
|
+
await store.lifecycle.setTenantQuota({ tenantId, userId, resourceKind: "run", limit: 100 });
|
|
344
|
+
await store.lifecycle.consumeTenantQuota({ tenantId, userId, resourceKind: "run" }); // fails closed when exhausted
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
Schema **v5** migration `005_lifecycle_hold_quota` adds `prism_legal_holds` and `prism_tenant_quotas`. Legal hold always blocks delete for the held resource id. Export pages are redacted refs only (no prompts/bodies/secrets).
|
|
348
|
+
|
|
349
|
+
Host background jobs may still:
|
|
338
350
|
|
|
339
351
|
1. Select policies whose `max_age_days`, `max_entries_per_session`, or `max_total_bytes` thresholds are exceeded.
|
|
340
|
-
2.
|
|
341
|
-
3. Respect `applied_kinds`
|
|
342
|
-
4.
|
|
343
|
-
5. Write audit metadata to the migration or host audit log; do not delete the policy row unless explicitly requested.
|
|
352
|
+
2. Pass candidate session ids into `applyRetention` (or let SQL adapters discover expired sessions).
|
|
353
|
+
3. Respect `applied_kinds` when selecting candidates.
|
|
354
|
+
4. Never silently purge under hold.
|
|
344
355
|
|
|
345
|
-
Retention jobs should not run inside the agent/session runtime.
|
|
356
|
+
Retention jobs should not run inside the agent/session runtime.
|
|
346
357
|
|
|
347
358
|
## Migrations
|
|
348
359
|
|
|
349
|
-
Hosts own schema migrations. Prism publishes only the TypeScript contracts; no DDL is generated or executed by the core library. First-party SQLite/PostgreSQL adapters automatically verify their checked-in schema-
|
|
360
|
+
Hosts own schema migrations. Prism publishes only the TypeScript contracts; no DDL is generated or executed by the core library. First-party SQLite/PostgreSQL adapters automatically verify their checked-in schema-v5 history and catalog at open, before runtime writes. Their catalog reads are bounded metadata queries/PRAGMAs, not table-data scans.
|
|
350
361
|
|
|
351
362
|
Each new adapter-owned migration row records the contract SHA-256 checksum. A complete known v0.0.5 history whose checksum values are all `NULL` is a one-time compatibility case: under the SQLite transaction or PostgreSQL advisory transaction lock, the adapter verifies the full current shape, backfills all checksums, and continues. Unknown/duplicate/out-of-order/name-version/checksum mismatch, mixed/partial legacy values, or any missing/renamed/wrong-type/null/default/key/index artifact fails closed. Restore or apply a reviewed host migration; never edit checksums to silence drift.
|
|
352
363
|
|
package/docs/extensions.md
CHANGED
|
@@ -122,6 +122,7 @@ await kernel.middleware.run("provider_request", { metadata: {} });
|
|
|
122
122
|
- Do not put resolved credential values in extension events, registry metadata, docs, logs, prompts, or session stores.
|
|
123
123
|
- Event and middleware dispatch are ordered and dependency-free. They use no timers, background workers, filesystem discovery, network calls, provider calls, or tool execution.
|
|
124
124
|
- Extension middleware cannot bypass host tool permissions: tool dispatch re-checks active registry lookup, filters, and object arguments after `tool_call` middleware. Skills that reference `toolNames` are checked against host-active tools by `resolveActiveSkills()`.
|
|
125
|
+
- Optional `loadPolicy: { allowList?, verifySignature? }` on `createExtensionKernel` runs before `setup`. Unallowlisted or unsigned (when `verifySignature` is set) extensions fail closed. Put host-attested digests on `Extension.signature`.
|
|
125
126
|
|
|
126
127
|
## Related APIs
|
|
127
128
|
|
package/docs/guardrails.md
CHANGED
|
@@ -65,10 +65,13 @@ Guardrails are callbacks supplied by the host. Prism does not discover, load, re
|
|
|
65
65
|
|
|
66
66
|
## Security and performance notes
|
|
67
67
|
|
|
68
|
+
Optional `@arnilo/prism-policy` can record guardrail outcomes via `recordGuardrailDecision` (evidence refs only; see [Policy and audit](policy-and-audit.md)).
|
|
69
|
+
|
|
68
70
|
Output buffering prevents blocked provider content from reaching subscribers, session entries, ledgers, parsers, delegation, or tools. Tool-output checks receive raw results but Prism discards blocked raw output before event, ledger, transcript, or MCP exposure. Redaction replaces exact known values only; it is not general secret detection. Parallel checks receive an abort signal, but callback code must honor it to stop in-flight work. Browser snapshots and page text from `@arnilo/prism-browser` are untrusted external content: never allow them to modify tools, permissions, credentials, or policy. Browser mutations still require host `ExecutionPolicy`/approval; prompt-injection text in a page cannot grant upload/download release.
|
|
69
71
|
|
|
70
72
|
## Related APIs
|
|
71
73
|
|
|
74
|
+
- [Policy and audit](policy-and-audit.md): optional attributable decision ledger for guardrail outcomes.
|
|
72
75
|
- [Agent/session runtime](agent-session-runtime.md)
|
|
73
76
|
- [Tools](tools.md)
|
|
74
77
|
- [Browser automation](browser-automation.md)
|
package/docs/host-security.md
CHANGED
|
@@ -34,6 +34,8 @@ Start from explicit host inputs. Do not let runtime code discover security state
|
|
|
34
34
|
| Durable interruption | host checkpoint + session stores, exact ownership | `RunOptions.runState`, `resumeAgentRun()`, `createAgentRunLifecycle()`, `createSecureAgent()` |
|
|
35
35
|
| Extensions | explicit package imports only | `createExtensionKernel`, `ExtensionAPI` |
|
|
36
36
|
| Remote agent/workflow API | host authentication + ownership mapping | `@arnilo/prism-server`, `createPrismHandler()` |
|
|
37
|
+
| Authenticated identity | host `IdentityVerifier` → verified `AgentIdentity` | [Agent identity](agent-identity.md), `assertIdentityActive`, `narrowIdentity` |
|
|
38
|
+
| Policy decision audit | optional redacted ledger + host WORM sink | [Policy and audit](policy-and-audit.md), `@arnilo/prism-policy` |
|
|
37
39
|
| MCP server exposure | host MCP auth + selected capability list | `createPrismMcpServer()`, `createPrismMcpWebHandler()` |
|
|
38
40
|
|
|
39
41
|
## Outputs / response / events
|
|
@@ -144,7 +146,8 @@ Wire those values where they matter: provider adapters receive the resolved cred
|
|
|
144
146
|
- LLM compaction always sends finite summary `maxTokens`, retains bounded deltas/events, and bounds/redacts provider/factory/policy error detail. Observational-memory workers cap turns, calls, arguments, results, transcript, and surfaced errors; unknown tools fail before execution, while invalid results can only be rejected after a host tool returns and may therefore follow side effects. Pass all known provider/credential/tool secrets into compaction/runtime options; exact replacement is not secret discovery.
|
|
145
147
|
- Default remote-media loading resolves every DNS answer, rejects the hostname if any address is non-public, and pins one validated address through the request. Explicit `allowedHostnames` can trust private destinations. A host-supplied `fetch` owns DNS/rebinding/proxy/redirect safety; a custom `requestUrl` must connect to its supplied validated address.
|
|
146
148
|
- Permission checks happen before tool validation and before `tool.execute()`. Middleware cannot grant permission by renaming a tool.
|
|
147
|
-
- Session stores and ledgers receive redacted values when a redactor is active, but durable storage remains host-owned. Enforce tenant/account/user ownership and
|
|
149
|
+
- Session stores and ledgers receive redacted values when a redactor is active, but durable storage remains host-owned. Enforce tenant/account/user ownership, retention, legal hold, and quotas via `ProductionPersistenceStore.lifecycle` (or host-equivalent DB controls). Hold always blocks delete.
|
|
150
|
+
- Prefer `createExtensionKernel({ loadPolicy })` allow-list/signature checks before loading third-party extension packages.
|
|
148
151
|
- Provider-owned auth/content/session/cache/security headers win over caller headers in adapters that merge headers.
|
|
149
152
|
- Security checks are bounded explicit calls on the active path. Prism adds no hidden global middleware, background workers, watchers, network calls, or filesystem scans.
|
|
150
153
|
|
|
@@ -172,6 +175,7 @@ PostgreSQL TLS/network policy, MCP endpoint trust/credentials and egress policy
|
|
|
172
175
|
## Web research boundaries
|
|
173
176
|
|
|
174
177
|
- Construct `@arnilo/prism-web-tools` with one host-selected Brave or Exa adapter; never expose adapter/provider/credential/schema selection to model arguments.
|
|
178
|
+
- Construct `@arnilo/prism-work-tools` with host-pinned CLI binary + isolated `configDir` + verified `AgentIdentity` (M365 and/or GWS). Never pass model-built command strings, `login`/`setup`/`auth`/`schema`/`--debug`, or credentials in argv. Mutations require draft approval; external recipients and anonymous/`anyone` shares fail closed.
|
|
175
179
|
- Provider API origins are fixed exact HTTPS origins and redirects fail. Credentials resolve immediately before I/O; remote bodies and secrets are excluded from errors/results/telemetry.
|
|
176
180
|
- Firecrawl targets reject userinfo, non-HTTP(S), private literals, and policy-denied hosts. Supply `validateUrl` for host DNS/rebinding/egress checks. Firecrawl performs remote retrieval, so Prism cannot pin target DNS after handoff.
|
|
177
181
|
- Treat every snippet, highlight, Markdown byte, metadata field, and extracted JSON value as prompt-injection-capable untrusted data. Never elevate it into system instructions or let it modify tools, permissions, trust, credentials, routing, or extraction schema.
|
package/docs/index.md
CHANGED
|
@@ -5,6 +5,11 @@ Prism is a TypeScript/Node.js agent harness. Host apps and extension packages ow
|
|
|
5
5
|
## Public contracts
|
|
6
6
|
- [Public contracts](public-contracts.md): type shapes for messages, agents, tools, stores, generic `CheckpointStore`, atomic `LeaseStore`, bounded `EventMultiplexer`, resources, credentials, and events.
|
|
7
7
|
|
|
8
|
+
## Identity and governance
|
|
9
|
+
- [Agent identity](agent-identity.md): host-verified `Principal` / `AgentIdentity`, delegation narrowing, ownership projection, and redacted telemetry refs for enterprise runs/tools/MCP/A2A/workflows.
|
|
10
|
+
- [Policy and audit](policy-and-audit.md): optional `@arnilo/prism-policy` decision ledger (allow/deny/modify/approval), evidence refs only, and cursor-paginated WORM export.
|
|
11
|
+
- [Model routing](model-routing.md): optional `@arnilo/prism-model-router` allow-list/residency/budget/rate/circuit/fallback governance over `ProviderResolver` with redacted diagnostics.
|
|
12
|
+
|
|
8
13
|
## Agent/session runtime
|
|
9
14
|
- [Agent/session runtime](agent-session-runtime.md): create explicit or opt-in secure agents/sessions, get direct `AgentRunResult` values from `run`/`prompt`, mid-run `steer` (turn-boundary or softInterrupt), use integrated `stream()`/`resumeAgentRunStream()`, subscribe to normalized events, and expose opted-in durable lifecycle capabilities.
|
|
10
15
|
- [Agent definitions](agent-definitions.md): resolve declarative `AgentDefinition` values via `resolveAgentDefinition`, and turn app-config `<configRoot>/agents/<name>/AGENT.md` bundles into runnable agents via `discoverAgentBundles` / `resolveAgentBundle` (explicit tool/skill activation by name, fail-closed omitted capabilities, migration-only `activateAllCapabilities`, strict duplicate scope checks, configurable prompt layers, no auto-discovery).
|
|
@@ -24,10 +29,10 @@ Prism is a TypeScript/Node.js agent harness. Host apps and extension packages ow
|
|
|
24
29
|
- [Working and semantic memory](working-and-semantic-memory.md): optional `@arnilo/prism-memory` working-memory store, semantic recall, finite Embedder/VectorStore contracts, in-memory adapters, and PostgreSQL/pgvector path.
|
|
25
30
|
- [Session stores](session-stores.md): `SessionStore` contract, `SessionAppendOptions`, `SessionAppendConflictError`, branch handles, `readBranchPath`, optional bounded `searchSessions` / `SessionIndex` (memory linear|unsupported), and dev-vs-production branch reads — start here for session persistence.
|
|
26
31
|
- [Session stores and branching](session-stores-and-branching.md): detailed branch semantics and helper reference (kept for compatibility; links back to the canonical atomic append / branch-handle sections).
|
|
27
|
-
- [Database persistence](database-persistence.md): production persistence contracts, shared checksummed migration/full-shape catalog primitives (`@arnilo/prism/testing/persistence-schema`), conditional append, indexes, `readBranchPath`, reference relational schema, retention, and NoSQL mapping.
|
|
32
|
+
- [Database persistence](database-persistence.md): production persistence contracts, shared checksummed migration/full-shape catalog primitives (`@arnilo/prism/testing/persistence-schema`), conditional append, indexes, `readBranchPath`, reference relational schema, retention/legal-hold/quota lifecycle (`lifecycle`), and NoSQL mapping.
|
|
28
33
|
- [SQLite persistence](sqlite-persistence.md): optional `better-sqlite3` adapter with session/run storage, checkpoints/leases, feedback, FTS `searchSessions` (migration-v4), and transactionally verified/backfilled migration metadata.
|
|
29
34
|
- [PostgreSQL persistence](postgres-persistence.md): optional pooled `pg` adapter with session/run/checkpoint/lease/feedback storage, FTS `searchSessions` (migration-v4), advisory-locked checksummed/full-shape migrations, and opt-in live conformance.
|
|
30
|
-
- [Migration guide](migration.md): **0.0.
|
|
35
|
+
- [Migration guide](migration.md): **0.0.13** enterprise identity/policy/router/work connectors, cloud providers, server deployment seams, persistence schema v5, and explicit **0.0.14+** deferrals; plus 0.0.12 AG-UI/ACP, 0.0.11 coding-harness fundamentals, 0.0.10 workspace modes, and 0.0.9 coding/browser surfaces.
|
|
31
36
|
- [Node JSONL session store](node-jsonl-session-store.md): development-only JSONL file adapter for single-process Node hosts; no cross-process safety; `searchSessions` throws `SessionSearchUnsupportedError`.
|
|
32
37
|
- [Persistence, credentials, and multimodality primitives](persistence-credentials-multimodality-primitives.md): Plan 056 inventory — session/run-ledger/persistence contracts, credential/OAuth seams, content/resource/model capabilities, package dependency matrix, conformance matrix, and threat model for production adapters.
|
|
33
38
|
|
|
@@ -40,9 +45,10 @@ Prism is a TypeScript/Node.js agent harness. Host apps and extension packages ow
|
|
|
40
45
|
- [Use-case model selection](use-case-model-selection.md): bind `{ model?, provider?, thinkingLevel? }` for observational memory, LLM compaction, and other non-session LLM jobs with explicit session-model fallback via `resolveUseCaseModel`.
|
|
41
46
|
- [Provider request policies](provider-request-policies.md): chain `ProviderRequestPolicy` hooks, use `createSessionCachePolicy`, and merge legacy/structured cache options safely.
|
|
42
47
|
- [Provider packages](provider-packages.md): define explicit provider packages, model metadata, auth descriptors, request/cache policies, provider-owned header precedence, and the 0.0.12 provider-authorized OAuth matrix without package discovery or provider-specific core behavior; includes a first-party cache behavior summary and the **caller-gated on-demand model discovery** contract (`list*Models`, setup zero-fetch).
|
|
43
|
-
- Phase 12 package workspaces: [`@arnilo/prism-provider-openai`](providers/openai.md), [`@arnilo/prism-provider-anthropic`](providers/anthropic.md) (native Messages, `cache_control`, thinking, caller-gated `listAnthropicModels`), [`@arnilo/prism-provider-google`](providers/google.md) (native Gemini `generateContent` SSE, caller-gated `listGoogleModels
|
|
48
|
+
- Phase 12 package workspaces: [`@arnilo/prism-provider-openai`](providers/openai.md), [`@arnilo/prism-provider-anthropic`](providers/anthropic.md) (native Messages, `cache_control`, thinking, caller-gated `listAnthropicModels`), [`@arnilo/prism-provider-google`](providers/google.md) (native Gemini `generateContent` SSE, caller-gated `listGoogleModels`), [`@arnilo/prism-provider-opencode-go`](providers/opencode-go.md) (official Go open models, dual-route Anthropic/OpenAI, caller-gated `listOpenCodeGoModels`, `reasoning_content`/thinking preserve), [`@arnilo/prism-provider-openrouter`](providers/openrouter.md) (app-controlled catalog, caller-gated `listOpenRouterModels`, `reasoning` merge/preserve, `cache_control` + sticky `session_id`), [`@arnilo/prism-provider-zai`](providers/zai.md) (official `thinking`/`reasoning_effort`/`tool_stream`, implicit cache, caller-gated `listZaiModels`), [`@arnilo/prism-provider-kimi`](providers/kimi.md), and [`@arnilo/prism-provider-neuralwatt`](providers/neuralwatt.md) with implicit vLLM prefix caching, reasoning controls (`reasoning_effort`/`thinking_token_budget`/`enable_thinking`/`preserve_thinking`/`clear_thinking`), reasoning preservation, OpenAI-style tool-call loop, quota, telemetry, and retry classification helpers.
|
|
49
|
+
- Phase 8 enterprise cloud (workload identity; separate from consumer Anthropic/Google): [`@arnilo/prism-provider-azure`](providers/azure.md) (Entra / Foundry), [`@arnilo/prism-provider-bedrock`](providers/bedrock.md) (IAM/IRSA + region/PrivateLink), [`@arnilo/prism-provider-vertex`](providers/vertex.md) (ADC / Vertex OpenAPI).
|
|
44
50
|
- Optional AI SDK adapter: [`@arnilo/prism-provider-ai-sdk`](providers/ai-sdk.md) maps host-owned `LanguageModelV4` models onto Prism `AIProvider` streams (specification v4; no Prism catalog; maps `finish.usage` cache read/write tokens; reasoning is host-model-owned).
|
|
45
|
-
- [OpenAI-compatible provider](providers/openai-compatible.md): optional provider subpath using native or injected `fetch` for Chat Completions streaming.
|
|
51
|
+
- [OpenAI-compatible provider](providers/openai-compatible.md): optional provider subpath using native or injected `fetch` for Chat Completions streaming (`chatCompletionsUrl` / `authStyle` overrides for enterprise adapters).
|
|
46
52
|
|
|
47
53
|
## Input, prompt, and context assembly
|
|
48
54
|
- [SDK customization guide](customization.md): map provider resolution, middleware, context, builders, injectors, loops, compaction, retry, stores, and skills to explicit host-wired APIs.
|
|
@@ -59,6 +65,8 @@ Prism is a TypeScript/Node.js agent harness. Host apps and extension packages ow
|
|
|
59
65
|
- [Tool validator JSON Schema package](../packages/tool-validator-json-schema/README.md): optional `@arnilo/prism-tool-validator-json-schema` adapter for `tool.parameters`.
|
|
60
66
|
- [MCP client bridge and server exposure](mcp-tools.md): SDK-1.29.0 bounded tools/resources/prompts, host-owned roots/sampling/elicitation, exact-origin DNS-pinned client transport, and principal-bound opt-in Streamable HTTP sessions.
|
|
61
67
|
- [Web search, fetch, and extraction](web-tools.md): optional host-selected Brave/Exa discovery and Firecrawl Markdown/schema tools with native fetch, stable citations, late credentials, finite limits, and explicit untrusted-content boundaries.
|
|
68
|
+
- [Work tools](work-tools.md): optional `@arnilo/prism-work-tools` identity-scoped M365 + GWS connectors (hard-coded CLI argv, draft-then-approve, idempotency, shared result shapes).
|
|
69
|
+
- [Work connectors](work-connectors.md): connector principles, capability gates, and out-of-scope boundaries for Microsoft 365 / Google Workspace.
|
|
62
70
|
- [Browser automation](browser-automation.md): optional `@arnilo/prism-browser` with host-supplied Playwright contexts, AI-mode snapshots/refs, ordered `browser_open`/`browser_snapshot`/`browser_act`/`browser_close`, egress/side-effect/upload/download/screenshot policy, and finite page/action/snapshot/network/artifact caps.
|
|
63
71
|
- [Coding agent tools](coding-agent-tools.md): optional `shell`, `read`, `write`, `edit`, `repo_list`, and `repo_search` definitions plus opt-in `createGitTools()` / `coding_check`, opt-in `createAskUserDecisionTool` (single/multi/free-text + durable suspend glue), and `runCodingGoalVerify`; durable plan/todo Markdown helpers with workflow `state.coding` checkpoint metadata; streamed text pages, bounded repository list/search, finite Git/check/plan/ask caps, bounded image/edit reads and write/edit payloads, finite shell wall/total-output limits, secure host-owned spill cleanup, pluggable bounded operation contracts, per-path mutation serialization, and optional `ExecutionPolicy`. Limits do not sandbox host access—gate with permission/trust policy and `@arnilo/prism-coding-security`.
|
|
64
72
|
- [Coding execution approval and sandboxing](coding-security.md): path/command approval, identity-scoped caching, shell-turn exclusivity, required `workspaceMode` (`host`/`sandbox`) with fail-closed mixed wiring, `createSandboxCodingComposition()` containment metadata, and the disposable Docker/OCI sandbox reference with bounded workspace import/export.
|
|
@@ -76,7 +84,7 @@ Prism is a TypeScript/Node.js agent harness. Host apps and extension packages ow
|
|
|
76
84
|
- [Resource loading](resource-loading.md): decode text, JSON, binary, and manifest resources through caller-provided loaders with bounded byte limits.
|
|
77
85
|
|
|
78
86
|
## Server/API
|
|
79
|
-
- [Web-standard server handler](server.md): optional framework-free authorized direct/SSE agent,
|
|
87
|
+
- [Web-standard server handler](server.md): optional framework-free authorized direct/SSE agent, durable agent lifecycle, durable workflow routes, plus optional health/drain/rate-limit/replay/deployment-lease seams; explicit bounds and zero default exposure.
|
|
80
88
|
|
|
81
89
|
## Multi-agent and interoperability
|
|
82
90
|
- [Supervisor delegation](supervisors.md): optional explicit child allow-list, derived memory scopes, narrowing-only permissions, lifecycle hooks, nested delegation, cancellation, finite budgets, host-projected delegation telemetry, and separate A2A durable adapter boundary.
|
|
@@ -93,7 +101,7 @@ Prism is a TypeScript/Node.js agent harness. Host apps and extension packages ow
|
|
|
93
101
|
- [Host security guide](host-security.md): fail-closed checklist for supply-chain/attestation/canary isolation, bounded credentials, AG-UI/ACP/A2A/web remote boundaries, untrusted external content, settings, redaction, trust roots, workflow ownership, coding I/O, permissions, persistence, extensions, and tool validation.
|
|
94
102
|
- [Security/auth/trust](settings-auth-trust-security.md): settings providers, credential helpers, trust/permission policies, redaction controls, host-owned settings/credentials wiring outside `AgentConfig`, and security-boundary hardening summary.
|
|
95
103
|
- [Credentials and redaction](credentials-and-redaction.md): compose explicit credential resolver order, use caller-supplied env objects/OAuth refresh helpers, resolve credentials only at the provider edge, redact known secret values, and follow the provider-authorized subscription OAuth matrix.
|
|
96
|
-
- [Credential storage](credential-storage.md): optional `@arnilo/prism-credentials-node` adapter with strict bounded AES-GCM envelopes, async finite scrypt, restrictive Unix files,
|
|
104
|
+
- [Credential storage](credential-storage.md): optional `@arnilo/prism-credentials-node` adapter with strict bounded AES-GCM envelopes, async finite scrypt, restrictive Unix files, abort-aware bounded system-keychain calls, and optional host-KMS wrap (`encryptWithHostKms`).
|
|
97
105
|
|
|
98
106
|
## Testing and examples
|
|
99
107
|
- Provider test doubles: `createMockProvider()` and provider event helpers are documented on the canonical Provider layer page above.
|
|
@@ -103,10 +111,11 @@ Prism is a TypeScript/Node.js agent harness. Host apps and extension packages ow
|
|
|
103
111
|
- [Compaction conformance](compaction-conformance.md): assert any `CompactionStrategy` returns a non-empty redacted summary and observes abort from `@arnilo/prism/testing/compaction-conformance`.
|
|
104
112
|
- [Tool conformance](tool-conformance.md): assert the tool-dispatch blocked-reason matrix (unknown/denied/invalid/permission/validator) and success path from `@arnilo/prism/testing/tool-conformance`.
|
|
105
113
|
- [Extension conformance](extension-conformance.md): assert an `Extension` setup runs, contributions stay inert, and setup errors are redacted or rethrown from `@arnilo/prism/testing/extension-conformance`.
|
|
106
|
-
- `examples/`: compile-checked typed examples and runnable mock demos (SDK basics, provider registration, auth, tools, [`examples/ag-ui-server.ts`](../examples/ag-ui-server.ts), cache-aware prompt assembly, NeuralWatt agent run ([`examples/neuralwatt-agent-run.ts`](../examples/neuralwatt-agent-run.ts)), [`examples/coding-compaction.ts`](../examples/coding-compaction.ts), stores/branching, structured-output/artifact-loop, CLI, RPC, workflow orchestration).
|
|
114
|
+
- `examples/`: compile-checked typed examples and runnable mock demos (SDK basics, provider registration, auth, tools, [`examples/ag-ui-server.ts`](../examples/ag-ui-server.ts), [`examples/enterprise-identity.ts`](../examples/enterprise-identity.ts), [`examples/enterprise-policy-audit.ts`](../examples/enterprise-policy-audit.ts), [`examples/enterprise-work-connectors.ts`](../examples/enterprise-work-connectors.ts), [`examples/server-deployment-seams.ts`](../examples/server-deployment-seams.ts), cache-aware prompt assembly, NeuralWatt agent run ([`examples/neuralwatt-agent-run.ts`](../examples/neuralwatt-agent-run.ts)), [`examples/coding-compaction.ts`](../examples/coding-compaction.ts), stores/branching, structured-output/artifact-loop, CLI, RPC, workflow orchestration).
|
|
107
115
|
|
|
108
116
|
## Release and install
|
|
109
|
-
- [Release and install](release-and-install.md): current
|
|
117
|
+
- [Release and install](release-and-install.md): current **41**-package graph (Phase 8 optional policy/router/enterprise providers/work-tools ship at 0.0.13; profile enrollment Task 10), install/tarball rules, pinned CodeQL/dependency/SBOM/license/secret/attestation gates, deterministic resumable publication, offline tests, protected live canaries, and sandbox-browser Docker/Playwright gates.
|
|
118
|
+
- [Review coverage (2026-07-23 Phase 8)](review-coverage-2026-07-23-phase-8.md): Plan 076 evidence freeze — enterprise identity/policy/router packages, Azure/Bedrock/Vertex adapters, server deployment seams, persistence lifecycle hooks, and M365/GWS work-connector bounds for 0.0.13.
|
|
110
119
|
- [Review coverage (2026-07-22 Phase 7)](review-coverage-2026-07-22-phase-7.md): Plan 075 evidence freeze — AG-UI/ACP package boundary, streamed durable resume, bounded replay/projection, coding compaction preset, and provider-authorized OAuth policy for 0.0.12.
|
|
111
120
|
- [Review coverage (2026-07-22 Phase 6)](review-coverage-2026-07-22-phase-6.md): Plan 074 evidence freeze — SessionIndex/search, contextBudget, native Anthropic/Google packages, goal→verify, steer, ask_user_decision (multi/free-text/suspend), finite limits, threats, and 0.0.11 release gates.
|
|
112
121
|
- [Review coverage (2026-07-21 Phase 5)](review-coverage-2026-07-21-phase-5.md): Plan 073 evidence freeze — unified workspace modes, primitive ownership, reused finite limits, threats, and 0.0.10 release gates.
|
package/docs/mcp-tools.md
CHANGED
|
@@ -198,6 +198,7 @@ Web handler defaults: 1 MiB request (8 MiB hard), 2 MiB response (16 MiB hard),
|
|
|
198
198
|
| Oversized/deep/wide server output | One aggregate byte/depth/property walk covers content, structured content, compatibility `toolResult`, and bounded remote errors before `ToolResult` |
|
|
199
199
|
| Unvalidated arguments | Register tools with `createJsonSchemaToolArgumentValidator()` at dispatch |
|
|
200
200
|
| Missing permission gate | Client direction: `PermissionPolicy` on `tool:mcp:<serverId>:<name>:execute`; server direction: required MCP `authorize` plus optional core `PermissionPolicy` |
|
|
201
|
+
| Unverified / widened identity | Optional `PrismMcpAuthorization.identity` must be host-verified and match ownership; invalid identity is forbidden before tool dispatch |
|
|
201
202
|
| Accidental server exposure | Empty default arrays/maps, duplicate-name rejection, explicit tools/commands/lifecycle only |
|
|
202
203
|
| Agent lifecycle data leak or cross-tenant resume | `agentRuns` requires exact tenant plus account/user ownership; core lifecycle returns public redacted state only and CAS-resumes with current agent/revision |
|
|
203
204
|
| Unbounded MCP HTTP | Bounded pre-parsed JSON, response bytes, concurrent requests, call timeout, SDK web-standard transport |
|
|
@@ -216,6 +217,7 @@ Official Exa/Firecrawl MCP servers may be tested only as explicit hardened proto
|
|
|
216
217
|
|
|
217
218
|
## Related APIs
|
|
218
219
|
|
|
220
|
+
- [Agent identity](agent-identity.md): optional verified identity on MCP authorize results
|
|
219
221
|
- [Tools](tools.md): registry, dispatch, validation
|
|
220
222
|
- [Web search, fetch, and extraction](web-tools.md): preferred direct bounded Brave/Exa/Firecrawl production path
|
|
221
223
|
- [Tool execution primitives](tool-execution-primitives.md): Plan 055 design and conformance matrix
|
package/docs/migration.md
CHANGED
|
@@ -7,6 +7,33 @@ Prism 0.0.6 preserves documented 0.0.3 agent construction except for two intenti
|
|
|
7
7
|
1. **`session.run()` / `session.prompt()` return `AgentRunResult`** and `session.stream()` starts one owned run after subscribing. Callers that ignored the previous `Promise<void>` keep working; failed/aborted runs reject with `AgentRunError` (`.result` attached).
|
|
8
8
|
2. **`AgentConfig.extensions` / `settings` / `credentials` are removed.** Wire extensions through `createExtensionKernel()`, read settings in the host, and pass credential resolvers to the provider edge.
|
|
9
9
|
|
|
10
|
+
## 0.0.12 → 0.0.13 enterprise identity, policy, routing, and work connectors (additive, pre-release)
|
|
11
|
+
|
|
12
|
+
Release **0.0.13** adds host-verified `Principal` / `AgentIdentity` on runs, tools, server/MCP/A2A/workflow seams. Hosts must supply an `IdentityVerifier` (`verify()` → `AgentIdentity` with `verified: true`); caller-asserted identity without host verification fails closed. See [Agent identity](agent-identity.md).
|
|
13
|
+
|
|
14
|
+
Optional `@arnilo/prism-policy` records allow/deny/modify/approval decisions with evidence refs only (no prompt/body/secret keys). Optional `@arnilo/prism-model-router` wraps `ProviderResolver` with allow-list, residency, token/cost budgets, rate limits, circuit breaking, and bounded fallbacks (`allowOpenRouterRouting` default false). See [Policy and audit](policy-and-audit.md) and [Model routing](model-routing.md).
|
|
15
|
+
|
|
16
|
+
| Surface | Before (0.0.12) | After (0.0.13) |
|
|
17
|
+
| --- | --- | --- |
|
|
18
|
+
| Run/tool identity | Ownership strings only | Optional verified `AgentIdentity`; `narrowIdentity` / propagation guards on delegation |
|
|
19
|
+
| Policy audit | Host-only logs | Optional append-only ledger + cursor export via `@arnilo/prism-policy` |
|
|
20
|
+
| Model governance | Host wraps resolver ad hoc | Optional `@arnilo/prism-model-router` before provider I/O |
|
|
21
|
+
| Work connectors | n/a | Optional `@arnilo/prism-work-tools` M365 + GWS; draft-then-approve; hard-coded CLI argv |
|
|
22
|
+
|
|
23
|
+
**Deferred to 0.0.14+:** conversation storage/service, Studio/control plane, internal auth DB, Redis/SQS queue adapters, local Office binaries. See [Phase 8 evidence](review-coverage-2026-07-23-phase-8.md).
|
|
24
|
+
|
|
25
|
+
Benchmark placeholder: `node scripts/benchmark-0.0.13.mjs` (release Task 10). Caps documented in [Performance limits](performance.md).
|
|
26
|
+
|
|
27
|
+
## 0.0.12 → 0.0.13 enterprise cloud providers (additive, pre-release)
|
|
28
|
+
|
|
29
|
+
Release **0.0.13** adds optional `@arnilo/prism-provider-azure`, `@arnilo/prism-provider-bedrock`, and `@arnilo/prism-provider-vertex` for workload-identity enterprise endpoints. Consumer `@arnilo/prism-provider-anthropic` / `@arnilo/prism-provider-google` stay unchanged (API-key). Install enterprise packages explicitly; pass host Entra/IAM/ADC credential callbacks; preserve region/private-endpoint URLs. No database migration.
|
|
30
|
+
|
|
31
|
+
Release **0.0.13** also extends `@arnilo/prism-server` with optional `createPrismHealthHandler`, `createPrismDrainController`, handler `rateLimit` / `drain` options, `createPrismEventReplay`, and `createPrismDeploymentLease`. Existing routes stay compatible. Queue adapters remain absent (Postgres coordinator polling stays default).
|
|
32
|
+
|
|
33
|
+
Persistence schema **v5** adds `005_lifecycle_hold_quota` (`prism_legal_holds`, `prism_tenant_quotas`) plus `ProductionPersistenceStore.lifecycle` / `createMemoryPersistenceLifecycle`. Extension kernels accept optional `loadPolicy` allow-list/signature checks. Credentials-node adds optional `encryptWithHostKms` / `decryptWithHostKms`.
|
|
34
|
+
|
|
35
|
+
Optional `@arnilo/prism-work-tools` (+ `./microsoft365`, `./google-workspace`) adds identity-scoped Outlook/Gmail/calendar/file/task tools over host-pinned `@pnp/cli-microsoft365` and `@googleworkspace/cli` with hard-coded argv templates, draft-then-approve mutations, package-local `IdempotencyStore`, and shared result normalizers.
|
|
36
|
+
|
|
10
37
|
## 0.0.11 → 0.0.12 coding harness interoperability (additive, pre-release)
|
|
11
38
|
|
|
12
39
|
Release **0.0.12** adds optional `@arnilo/prism-ag-ui` (root AG-UI and stable `./acp` sibling), generic `resumeAgentRunStream()` / `AgentRunLifecycle.resumeStream()`, and `createCodingCompactionStrategy()` from `@arnilo/prism-compaction-llm`. It adds no core UI dependency, session/database migration, listener, tool, editor/filesystem bridge, conversation/artifact service, worker, or background reconnect loop.
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# Model routing
|
|
2
|
+
|
|
3
|
+
## What it does
|
|
4
|
+
|
|
5
|
+
`@arnilo/prism-model-router` is an optional governance facade over an existing `ProviderResolver`. It enforces allow-lists, residency, token/cost budgets, rate limits, circuit breaking, and bounded fallbacks before provider selection, and emits redacted selection diagnostics. It does not implement a second provider runtime.
|
|
6
|
+
|
|
7
|
+
## When to use it
|
|
8
|
+
|
|
9
|
+
Use it for enterprise hosts that must deny models/regions before any provider call and attribute selection for audit. Skip it when a plain `createProviderResolver` allow-list is enough.
|
|
10
|
+
|
|
11
|
+
Do not put secrets, prompts, or raw OpenRouter keys into diagnostics. Do not honor `compat.openRouterRouting` unless `allowOpenRouterRouting: true`.
|
|
12
|
+
|
|
13
|
+
## Inputs / request
|
|
14
|
+
|
|
15
|
+
| API / field | Meaning |
|
|
16
|
+
| --- | --- |
|
|
17
|
+
| `createModelRouter({ resolver, ... })` | Wraps host `ProviderResolver` |
|
|
18
|
+
| `allowList.providers` / `allowList.models` | Exact provider id / model id or `provider/model` |
|
|
19
|
+
| `allowedResidencies` | Request residency must match when configured |
|
|
20
|
+
| `budgets` / per-call `maxTokens` / `maxCostUsd` | Finite non-negative ceilings; `recordUsage` charges |
|
|
21
|
+
| `rateLimit` | Per identity+model key window |
|
|
22
|
+
| `circuit` | Failure threshold + cooldown; keys capped |
|
|
23
|
+
| `fallbacks` | Ordered candidates after primary; total attempts capped |
|
|
24
|
+
| `allowOpenRouterRouting` | Default `false`; when false, routing metadata is stripped |
|
|
25
|
+
| `onDiagnostics` | Optional redacted hook (e.g. policy ledger evidence ref) |
|
|
26
|
+
| `router.resolve({ model, identity?, residency?, ... })` | Rich async selection |
|
|
27
|
+
| `router.providerSource` | Sync `ProviderResolver` facade for `AgentConfig` |
|
|
28
|
+
|
|
29
|
+
Frozen caps (default / hard): attempts `3 / 8`, circuit keys `1,024 / 16,384`, diagnostics `8 KiB / 64 KiB`.
|
|
30
|
+
|
|
31
|
+
## Outputs / response / events
|
|
32
|
+
|
|
33
|
+
- `ModelRouterResolveResult` — selected `provider` + possibly stripped `model`, `diagnostics`, and `providerRequestPolicy`.
|
|
34
|
+
- Deny throws `ModelRouterError` with code + redacted `diagnostics` (allow-list/residency/budget fail closed without calling resolver).
|
|
35
|
+
- `recordOutcome({ success })` opens/closes circuits; `recordUsage` advances budgets.
|
|
36
|
+
|
|
37
|
+
## Request/response example
|
|
38
|
+
|
|
39
|
+
```json
|
|
40
|
+
{
|
|
41
|
+
"outcome": "allow",
|
|
42
|
+
"selectedProvider": "openrouter",
|
|
43
|
+
"selectedModel": "auto",
|
|
44
|
+
"attempts": [
|
|
45
|
+
{ "provider": "openai", "model": "gpt-4o", "outcome": "circuit_open", "reason": "circuit_open" },
|
|
46
|
+
{ "provider": "openrouter", "model": "auto", "outcome": "selected" }
|
|
47
|
+
],
|
|
48
|
+
"identityRefs": { "tenantId": "t1", "principalId": "a1", "principalKind": "agent" },
|
|
49
|
+
"openRouterRoutingHonored": false,
|
|
50
|
+
"residency": "eu"
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Implementation example
|
|
55
|
+
|
|
56
|
+
```ts
|
|
57
|
+
import { createAgent, createProviderResolver } from "@arnilo/prism";
|
|
58
|
+
import { createModelRouter } from "@arnilo/prism-model-router";
|
|
59
|
+
|
|
60
|
+
const router = createModelRouter({
|
|
61
|
+
resolver: createProviderResolver(providers),
|
|
62
|
+
allowList: { providers: ["openai", "openrouter"] },
|
|
63
|
+
allowedResidencies: ["eu"],
|
|
64
|
+
fallbacks: [{ provider: "openrouter", model: "auto" }],
|
|
65
|
+
allowOpenRouterRouting: false,
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
const { provider, model, providerRequestPolicy } = await router.resolve({
|
|
69
|
+
model: sessionModel,
|
|
70
|
+
identity,
|
|
71
|
+
residency: "eu",
|
|
72
|
+
maxCostUsd: 0.25,
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
const agent = createAgent({
|
|
76
|
+
model,
|
|
77
|
+
provider,
|
|
78
|
+
providerRequestPolicies: [providerRequestPolicy],
|
|
79
|
+
});
|
|
80
|
+
// or: providerSource: router.providerSource
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Extension and configuration notes
|
|
84
|
+
|
|
85
|
+
Router is optional. Chain returned `providerRequestPolicy` with other `ProviderRequestPolicy` values. Wire `onDiagnostics` to `@arnilo/prism-policy` when audit export is required. OpenRouter package behavior is unchanged; routing metadata participates only when this gate allows it.
|
|
86
|
+
|
|
87
|
+
## Security and performance notes
|
|
88
|
+
|
|
89
|
+
- Allow-list and residency denies never call the underlying resolver.
|
|
90
|
+
- Budget/rate/circuit state is memory-capped; oldest keys evict.
|
|
91
|
+
- Diagnostics carry identity refs and attempt outcomes only — no prompts/secrets.
|
|
92
|
+
- Selection is O(attempts × map ops); no network I/O inside the router.
|
|
93
|
+
- Raising hard caps requires Phase 8 freeze + tests + docs updates.
|
|
94
|
+
|
|
95
|
+
## Related APIs
|
|
96
|
+
|
|
97
|
+
- [Provider layer](provider-layer.md)
|
|
98
|
+
- [Provider request policies](provider-request-policies.md)
|
|
99
|
+
- [OpenRouter](providers/openrouter.md)
|
|
100
|
+
- [Policy and audit](policy-and-audit.md)
|
|
101
|
+
- [Agent identity](agent-identity.md)
|
|
102
|
+
- Package README: [`@arnilo/prism-model-router`](../packages/model-router/README.md)
|
package/docs/observability.md
CHANGED
|
@@ -167,12 +167,14 @@ console.log(traceId, memory.spans.map((span) => span.name));
|
|
|
167
167
|
## Security and performance notes
|
|
168
168
|
|
|
169
169
|
- Default events are metadata-only — no prompts, streamed deltas, tool arguments, or credentials.
|
|
170
|
+
- Use `identityTelemetryAttributes(identity)` when attaching enterprise identity to run metadata or OTel attributes; it emits `prism.identity.*` refs only (tenant/principal/scope counts), never credential secrets or raw tokens.
|
|
170
171
|
- Opt-in content in other event types (`message_delta`, tool `result`) is still subject to `redactAgentEvent`.
|
|
171
172
|
- Metric labels stay low-cardinality (`gen_ai.operation.name`, `gen_ai.provider.name`, token type, controlled outcome/status, feedback rating bucket/link presence); never use session/run/request/call IDs, model output, comments, tag values, scorer/evaluation IDs, or arbitrary metadata as labels. Token usage is recorded once at provider operation scope.
|
|
172
173
|
- Target overhead when enabled is under 5% excluding exporter I/O; disabled hooks allocate no spans.
|
|
173
174
|
- Provider transport limits and redaction order are documented in [Provider primitives](provider-primitives.md).
|
|
174
175
|
|
|
175
176
|
## Related APIs
|
|
177
|
+
- [Agent identity](agent-identity.md): redacted identity attribute helper for telemetry.
|
|
176
178
|
- [Evaluations](evaluations.md): optional scorers can link scores to run/session/trace IDs from agent events.
|
|
177
179
|
|
|
178
180
|
- [Agent events](agent-events.md): full `AgentEvent` union and subscriber semantics.
|
package/docs/performance.md
CHANGED
|
@@ -455,6 +455,25 @@ Timings are one local Node v24.18.0 run over mock agents and an in-process fetch
|
|
|
455
455
|
|
|
456
456
|
No performance ceiling was raised. Core grew from Phase 0's 346.0 kB packed baseline to ~403.7 kB after documented APIs/templates, while the full package set remains ~690.6 kB packed. Follow-up review includes all six Phase 4-13 capability packages through `prism-all` and AI SDK interoperability through `prism-providers`; focused base/code/SDK profiles remain unchanged and no capability auto-activates. Manifest tarballs remain tiny: providers 1.4 kB and all 1.6 kB packed.
|
|
457
457
|
|
|
458
|
+
### 0.0.13 Phase 8 server deployment seams (2026-07-23)
|
|
459
|
+
|
|
460
|
+
Optional health/drain/rate-limit/replay/deployment-lease helpers on `@arnilo/prism-server`. No listener, queue adapter, or concurrency hard-cap raise.
|
|
461
|
+
|
|
462
|
+
| Surface | Result |
|
|
463
|
+
| --- | --- |
|
|
464
|
+
| Focused server suite | existing handler tests + 4 deployment seam tests pass |
|
|
465
|
+
| Health body | default 4 KiB / hard 64 KiB; detail requires authorize |
|
|
466
|
+
| Drain admit cutoff | default 30 s / hard 5 min; admits reject immediately on `beginDrain` |
|
|
467
|
+
| Replay page / cursor | 100 / 4 KiB default; 500 / 16 KiB hard |
|
|
468
|
+
| Concurrent runs | unchanged 16 / 256 |
|
|
469
|
+
| Queues | absent; use `createWorkflowCoordinator` polling until measured need |
|
|
470
|
+
|
|
471
|
+
### 0.0.13 Phase 8 identity, policy, router, and work connectors (2026-07-24)
|
|
472
|
+
|
|
473
|
+
Enterprise governance and connector caps (defaults / hard). Timings: `node scripts/benchmark-0.0.13.mjs`; `PRISM_BENCH_ITERATIONS` accepts 10–100,000 (default 100). Schema/bounds test: `node --test scripts/benchmark-0.0.13.test.mjs`. Default mode is network-free and reports identity/policy/router/work-connector/deployment throughput and p50/p95 with frozen budget refs in the report JSON. Bounds and hostile-input fixtures—not these host-local timings—are release gates.
|
|
474
|
+
|
|
475
|
+
Offline behavior tests (identity propagation, policy export, router deny paths, fake CLI argv) are release gates; live tenant canaries remain operator-gated.
|
|
476
|
+
|
|
458
477
|
## Related APIs
|
|
459
478
|
|
|
460
479
|
- [Agent events](agent-events.md): `SubscribeOptions` and `event_subscriber_overflow` event details.
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# Policy and audit
|
|
2
|
+
|
|
3
|
+
## What it does
|
|
4
|
+
|
|
5
|
+
`@arnilo/prism-policy` records redacted allow/deny/modify/approval decisions with policy version, actor refs from verified `AgentIdentity`, target, reason, expiry, and evidence references. Hosts export cursor-paginated pages to append-only/WORM sinks. The package does not embed a mandatory global policy engine, KMS, or cloud WORM SDK.
|
|
6
|
+
|
|
7
|
+
## When to use it
|
|
8
|
+
|
|
9
|
+
Use it when enterprise hosts need an attributable audit trail alongside existing guardrails, permission checks, and tool-approval interruptions. Skip it for single-tenant apps that only need `RunLedger` / guardrail events.
|
|
10
|
+
|
|
11
|
+
Do not store unrestricted prompts, tool argument bodies, JWTs, or credential secrets on decision records. Do not treat the reference memory/file adapters as production WORM.
|
|
12
|
+
|
|
13
|
+
## Inputs / request
|
|
14
|
+
|
|
15
|
+
| API / field | Meaning |
|
|
16
|
+
| --- | --- |
|
|
17
|
+
| `createPolicyEvaluator({ policyId, policyVersion, evaluate })` | Host rule callback stamped with immutable id/version |
|
|
18
|
+
| `PolicyEvaluateRequest` | Verified `identity`, `action`, `resource`, optional evaluator-only `context` (never persisted) |
|
|
19
|
+
| `AppendPolicyDecisionInput` | Decision fields + verified identity; ownership from identity or explicit scope |
|
|
20
|
+
| `createMemoryPolicyDecisionStore` / `createFilePolicyDecisionStore` | Append-only reference ledgers |
|
|
21
|
+
| `exportPolicyDecisions({ store, ownership, cursor, limit, sink? })` | Cursor pages; optional host WORM sink |
|
|
22
|
+
| `recordGuardrailDecision` / `recordPermissionDecision` / `recordToolApprovalDecision` | Optional bridges from existing decision points |
|
|
23
|
+
|
|
24
|
+
Frozen caps (default / hard): decision `8 KiB / 64 KiB`, reason or evidence ref `1 KiB / 8 KiB`, export page `100 / 500`.
|
|
25
|
+
|
|
26
|
+
## Outputs / response / events
|
|
27
|
+
|
|
28
|
+
- `PolicyDecisionRecord` — frozen redacted row (`actor` refs, `evidenceRefs`, no payload blob).
|
|
29
|
+
- `evaluateAndAppend` — evaluate then append in one call.
|
|
30
|
+
- Policy version mismatch (`requirePolicyVersion`) and unrestricted payload keys fail closed (`ERR_PRISM_POLICY_VERSION` / `ERR_PRISM_POLICY_PAYLOAD`).
|
|
31
|
+
- Missing/expired/unverified identity fails via core `assertIdentityActive` before append.
|
|
32
|
+
|
|
33
|
+
## Request/response example
|
|
34
|
+
|
|
35
|
+
```json
|
|
36
|
+
{
|
|
37
|
+
"id": "dec-1",
|
|
38
|
+
"policyId": "mail",
|
|
39
|
+
"policyVersion": "2026-07-23",
|
|
40
|
+
"outcome": "approval",
|
|
41
|
+
"actor": {
|
|
42
|
+
"tenantId": "tenant-1",
|
|
43
|
+
"userId": "user-1",
|
|
44
|
+
"principalId": "agent-42",
|
|
45
|
+
"principalKind": "agent",
|
|
46
|
+
"sponsorId": "sponsor-7"
|
|
47
|
+
},
|
|
48
|
+
"target": { "kind": "draft", "id": "d1" },
|
|
49
|
+
"reason": "external send",
|
|
50
|
+
"evidenceRefs": ["rule:external"],
|
|
51
|
+
"createdAt": "2026-07-23T12:00:00.000Z",
|
|
52
|
+
"tenantId": "tenant-1",
|
|
53
|
+
"userId": "user-1"
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Implementation example
|
|
58
|
+
|
|
59
|
+
```ts
|
|
60
|
+
import { type AgentIdentity } from "@arnilo/prism";
|
|
61
|
+
import {
|
|
62
|
+
createFilePolicyDecisionStore,
|
|
63
|
+
createPolicyEvaluator,
|
|
64
|
+
evaluateAndAppend,
|
|
65
|
+
exportPolicyDecisions,
|
|
66
|
+
recordToolApprovalDecision,
|
|
67
|
+
} from "@arnilo/prism-policy";
|
|
68
|
+
|
|
69
|
+
const evaluator = createPolicyEvaluator({
|
|
70
|
+
policyId: "mail",
|
|
71
|
+
policyVersion: "2026-07-23",
|
|
72
|
+
evaluate: ({ action }) =>
|
|
73
|
+
action === "mail.send"
|
|
74
|
+
? { outcome: "approval", reason: "external send", evidenceRefs: ["rule:external"] }
|
|
75
|
+
: { outcome: "allow" },
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
const store = createFilePolicyDecisionStore({
|
|
79
|
+
path: "/var/prism/policy-decisions.jsonl",
|
|
80
|
+
requirePolicyVersion: "2026-07-23",
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
await evaluateAndAppend(
|
|
84
|
+
{ identity, action: "mail.send", resource: { kind: "draft", id: "d1" } },
|
|
85
|
+
{ store, evaluator, id: crypto.randomUUID() },
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
await recordToolApprovalDecision({
|
|
89
|
+
store,
|
|
90
|
+
evaluator,
|
|
91
|
+
id: crypto.randomUUID(),
|
|
92
|
+
identity,
|
|
93
|
+
toolName: "mail.send",
|
|
94
|
+
toolCallId: "call-1",
|
|
95
|
+
evidenceRef: "run:abc/tool:call-1",
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
for await (const page of exportPolicyDecisions({
|
|
99
|
+
store,
|
|
100
|
+
tenantId: identity.tenantId,
|
|
101
|
+
userId: identity.userId,
|
|
102
|
+
sink: { async write(records) { await worm.append(records); } },
|
|
103
|
+
})) {
|
|
104
|
+
void page;
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Extension and configuration notes
|
|
109
|
+
|
|
110
|
+
Policy is optional. Hosts wire `record*` helpers or `evaluateAndAppend` at permission/guardrail/tool-approval/router/connector boundaries. Model-router and work-connector packages (later Phase 8 tasks) may call the same store when configured. Replace file/memory adapters with host WORM/KMS without changing record shape.
|
|
111
|
+
|
|
112
|
+
## Security and performance notes
|
|
113
|
+
|
|
114
|
+
- Approvals require verified `AgentIdentity`; actor fields are refs only.
|
|
115
|
+
- Policy version pin fails closed on mismatch.
|
|
116
|
+
- Unrestricted payload field names (`prompt`, `body`, `toolArguments`, …) are rejected before append.
|
|
117
|
+
- Evaluate/append are O(fields) and network-free in-package; remote WORM I/O stays in the host sink/adapter.
|
|
118
|
+
- Export never full-scans: page size is capped; raise hard caps only with Phase 8 freeze + tests + docs updates.
|
|
119
|
+
|
|
120
|
+
## Related APIs
|
|
121
|
+
|
|
122
|
+
- [Model routing](model-routing.md)
|
|
123
|
+
- [Agent identity](agent-identity.md)
|
|
124
|
+
- [Guardrails](guardrails.md)
|
|
125
|
+
- [Runs and usage ledger](runs-and-usage.md)
|
|
126
|
+
- [Host security](host-security.md)
|
|
127
|
+
- Package README: [`@arnilo/prism-policy`](../packages/policy/README.md)
|
|
@@ -116,7 +116,7 @@ PRISM_TEST_POSTGRES_URL="$DATABASE_URL" npm run test:postgres --workspace @arnil
|
|
|
116
116
|
- The package is optional and workspace-local; `@arnilo/prism` core has no PostgreSQL dependency.
|
|
117
117
|
- Schema names must match `^[a-zA-Z_][a-zA-Z0-9_]*$`; the adapter quotes them and never interpolates user values into identifier positions.
|
|
118
118
|
- `SessionAppendOptions` idempotency rows are durable in `prism_session_append_idempotency` and survive reopen.
|
|
119
|
-
- Schema version **
|
|
119
|
+
- Schema version **5** applies `001_init`, `002_usage_scope`, `003_run_feedback`, `004_session_search`, and `005_lifecycle_hold_quota`. Migration 003 adds immutable `prism_run_feedback` rows with run FK/cascade deletion and owner/run/trace cursor indexes. Migration 004 adds session search FTS (Postgres `tsvector` FTS table dual-written on append) plus `prism_sessions(updated_at, id)` cursor index; existing entries are backfilled once. `persistence.feedback` validates exact run ownership, bounds/redacts through optional `feedbackRedactor`, queries bounded pages, and deletes only exact-owned IDs. Search hits never include credentials; ownership filters apply when present. SQLite shares the same model with dialect-local DDL.
|
|
120
120
|
- Pass an existing `pg` `Pool` when your host already manages pooling, TLS, and credential rotation.
|
|
121
121
|
|
|
122
122
|
## Security and performance notes
|
|
@@ -24,7 +24,10 @@ Do not use provider packages as a package manager, credential store, env loader,
|
|
|
24
24
|
| --- | --- | --- |
|
|
25
25
|
| `@arnilo/prism-provider-openai` | `api_key` for `openai`; `oauth` for `openai-codex` | Existing host-invoked OpenAI Codex PKCE/device-code flow only. |
|
|
26
26
|
| `@arnilo/prism-provider-anthropic` | `api_key` only | No Claude Code/Claude.ai subscription OAuth, credential-file/setup-token import, or routing. [Anthropic requires product developers to use API keys or supported cloud providers](https://docs.anthropic.com/en/docs/claude-code/legal-and-compliance). |
|
|
27
|
-
| `@arnilo/prism-provider-google` | `api_key` only | No Gemini CLI OAuth or credential/token import. [Gemini CLI prohibits third-party OAuth piggybacking](https://github.com/google-gemini/gemini-cli/blob/main/docs/resources/tos-privacy.md); use Google AI Studio
|
|
27
|
+
| `@arnilo/prism-provider-google` | `api_key` only | No Gemini CLI OAuth or credential/token import. [Gemini CLI prohibits third-party OAuth piggybacking](https://github.com/google-gemini/gemini-cli/blob/main/docs/resources/tos-privacy.md); use Google AI Studio API keys. Vertex/ADC uses separate [`@arnilo/prism-provider-vertex`](providers/vertex.md). |
|
|
28
|
+
| `@arnilo/prism-provider-azure` | host Entra token or Azure resource key | Workload identity via `credential` callback; endpoint host preserved ([docs](providers/azure.md)). |
|
|
29
|
+
| `@arnilo/prism-provider-bedrock` | host IAM/IRSA credentials | SigV4 over OpenAI-compatible Bedrock Runtime; region/PrivateLink preserved ([docs](providers/bedrock.md)). |
|
|
30
|
+
| `@arnilo/prism-provider-vertex` | host ADC / workload token | OpenAPI-compatible Vertex endpoint; separate from consumer Google package ([docs](providers/vertex.md)). |
|
|
28
31
|
|
|
29
32
|
A future provider-local OAuth package must first have explicit third-party permission and documented authorize/token/refresh flow. Before it registers an OAuth descriptor, it must add bounded request/response, abort, PKCE/state where required, expiry/refresh, secret-redaction, durable-store round-trip, and offline protocol tests. Do not add a generic OAuth framework, CLI credential scanner, automatic refresh timer, or success stub.
|
|
30
33
|
|
|
@@ -268,6 +271,8 @@ await kernel.load([pkg]);
|
|
|
268
271
|
- Provider-specific behavior belongs in provider packages, not Prism core.
|
|
269
272
|
- Adapter serializers should preserve Prism content blocks (text, thinking, tool_call, tool_result, and image when the model declares image input) in provider-native request shape, or fail explicitly when a block is unsupported.
|
|
270
273
|
- Adapter header merging must put caller-supplied `ProviderRequest.options.headers` first and provider-owned headers last. Caller headers may add non-owned headers, but cannot replace resolved credentials, content type, session/cache/security headers, or provider attribution headers.
|
|
274
|
+
- For allow-list/residency/budget/circuit selection before resolve, use optional `@arnilo/prism-model-router` over `createProviderResolver` — do not fork provider packages for governance.
|
|
275
|
+
- Enterprise cloud adapters (`azure` / `bedrock` / `vertex`) stay separate from consumer Anthropic/Google packages and authenticate only through host credential callbacks.
|
|
271
276
|
|
|
272
277
|
## Manifest declarations
|
|
273
278
|
|
|
@@ -291,6 +296,8 @@ Manifest declarations are inert. The host must later resolve them through regist
|
|
|
291
296
|
|
|
292
297
|
## Related APIs
|
|
293
298
|
|
|
299
|
+
- [Model routing](model-routing.md): optional governance router over `ProviderResolver`.
|
|
300
|
+
- [Azure OpenAI / Foundry](providers/azure.md) / [Amazon Bedrock](providers/bedrock.md) / [Google Vertex AI](providers/vertex.md): enterprise workload-identity packages.
|
|
294
301
|
- [Provider layer](provider-layer.md): provider/model registries and provider events.
|
|
295
302
|
- [Provider conformance](provider-conformance.md): reusable network-free checks for provider adapters.
|
|
296
303
|
- [Contribution registries](contribution-registries.md): registry bundle and extension contribution points.
|
|
@@ -104,9 +104,11 @@ Policy output should stay generic: use `ProviderRequestOptions.cache`, `headers`
|
|
|
104
104
|
- Cache keys must never be credentials.
|
|
105
105
|
- Policy chains are O(number of policies) plus option merge cost.
|
|
106
106
|
- Policies should be pure and synchronous unless the host explicitly accepts async work.
|
|
107
|
+
- Optional `@arnilo/prism-model-router` returns a `ProviderRequestPolicy` that strips `openRouterRouting` unless governance allows it — chain it with other policies.
|
|
107
108
|
|
|
108
109
|
## Related APIs
|
|
109
110
|
|
|
111
|
+
- [Model routing](model-routing.md): governance facade that emits a chainable OpenRouter routing gate policy.
|
|
110
112
|
- [Provider caching](provider-caching.md): structured cache hints and helpers.
|
|
111
113
|
- [Provider packages](provider-packages.md): registering policies from extension packages.
|
|
112
114
|
- [Provider layer](provider-layer.md): provider request flow and `AIProvider.generate()`.
|