@atlasauth/pca-rag 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Atlas Authorization
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,55 @@
1
- # Temporary Holding Version
1
+ # @atlasauth/pca-rag
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Fine-grained authorization for RAG, built on Proof-Carrying Authority (PCA). At retrieval time it filters candidate documents down to the ones a given principal may see, deciding each one with the PCA policy engine. Every filtering decision is recorded with a content-addressed digest, so you can show the model was handed only authorized data.
4
+
5
+ - Documents carry ACL metadata: a `{ relation, object }` entry, or `relation:object` tag strings.
6
+ - Policy is either raw PCA predicates or an OpenFGA / Zanzibar model plus tuples (compiled through `@atlasauth/pca-policy-bridge`, including relation closures such as "viewer from parent").
7
+ - **Fails closed**: a document is admitted only when a permit predicate matches and no deny matches. No ACL, an unresolved relation, a malformed document, or an incomplete policy translation drops the document.
8
+
9
+ ## Install
10
+
11
+ ```sh
12
+ npm i @atlasauth/pca-rag
13
+ ```
14
+
15
+ Depends on `@atlasauth/pca` and `@atlasauth/pca-policy-bridge`.
16
+
17
+ ## Usage
18
+
19
+ ```ts
20
+ import { filterDocuments, withPcaFilter } from '@atlasauth/pca-rag';
21
+
22
+ const policy = { openfga: { model, tuples } }; // OpenFGA authorization model + relationship tuples
23
+
24
+ const candidates = [
25
+ { id: 'readme', text: '...', acl: { relation: 'can_view', object: 'document:readme' } },
26
+ { id: 'spec', text: '...', tags: ['can_view:document:spec'] },
27
+ ];
28
+
29
+ const { documents, decision } = filterDocuments('user:alice', candidates, policy);
30
+ decision.allowedIds; // ids the model may see
31
+ decision.droppedIds; // ids dropped, with a reason per document in decision.decisions
32
+ decision.digest; // b64u commitment to the decision set, bindable into a receipt or proof
33
+
34
+ // Or wrap any retriever so results are filtered before they reach the model:
35
+ const safe = withPcaFilter(retriever, 'user:alice', policy); // retriever.retrieve(query, k)
36
+ const docs = await safe.retrieve('how do I deploy?');
37
+ safe.lastDecision(); // audit trail for the last call
38
+ ```
39
+
40
+ Compile once with `compilePolicy(policy)` and reuse the result to avoid recompiling per call. To derive the principal from a verified PCActn, use `principalFromPCActn(pcactn, { id })`.
41
+
42
+ ## API
43
+
44
+ - `filterDocuments(principal, candidates, policy, opts?)` returns `{ documents, decision }`
45
+ - `withPcaFilter(retriever, principal, policy, opts?)` generic retriever wrapper
46
+ - `withLangChainPcaFilter(...)`, `withLlamaIndexPcaFilter(...)` structural adapters for LangChain and LlamaIndex retrievers (no dependency on either library)
47
+ - `compilePolicy`, `aclsFromMetadata`, `principalFromPCActn`
48
+
49
+ ## Status
50
+
51
+ Part of [Proof-Carrying Authority](https://github.com/Atlas-Authorization/pca). This filters retrieval results; it does not control what a model does with documents it is allowed to see. PCA's cryptography has not been independently audited.
52
+
53
+ ## License
54
+
55
+ MIT - see LICENSE
@@ -0,0 +1,226 @@
1
+ /**
2
+ * @atlasauth/pca-rag — FGA-for-RAG.
3
+ *
4
+ * Retrieval-time, per-principal document filtering driven by the PCA policy engine. Given a
5
+ * principal (or a verified PCActn's holder), a candidate set of documents that each carry ACL
6
+ * metadata (a `{ relation, object }` ACL entry, or `relation:object` tags), and a policy (raw PCA
7
+ * predicates, or an imported OpenFGA/Zanzibar ReBAC model+tuples), this returns ONLY the documents
8
+ * the principal may see — deciding every candidate through the core evaluator / `member_of` relation
9
+ * closure in `@atlasauth/pca`, and reusing `@atlasauth/pca-policy-bridge` to compile ReBAC relation
10
+ * checks into PCA predicates.
11
+ *
12
+ * Two properties make this suitable for the PCA proof trace:
13
+ * 1. FAIL CLOSED. A document is admitted ONLY when a permit predicate cleanly matches (verb =
14
+ * relation, resource = object, every `where` condition `true`) and no deny predicate matches.
15
+ * Anything unknown — no ACL, an unresolved relation, a malformed document, an incomplete policy
16
+ * translation — drops the document. The model can never see an unauthorized chunk.
17
+ * 2. AUDITABLE. Every decision is captured in a {@link FilterDecision}: which documents passed,
18
+ * which were dropped and why, the exact permit predicate that authorized each one, and a
19
+ * content-addressed `digest` of the whole decision set that can be bound into a receipt / proof.
20
+ *
21
+ * Decisions use the SAME evaluator the adjudicator uses, so "what the retriever filtered" and "what
22
+ * the authority system would admit" cannot drift apart.
23
+ */
24
+ import type { PCActn, Predicate } from '@atlasauth/pca';
25
+ import { type TranslationReport } from '@atlasauth/pca-policy-bridge';
26
+ /**
27
+ * The retrieval principal. `id` is matched against the policy's subject (`subject.id` in a PCA
28
+ * predicate, the `user` of an OpenFGA tuple). `attributes` are exposed to policy conditions as
29
+ * `subject.*`; `env` is exposed as `env.*` (e.g. a group-adjacency map a `member_of` condition's
30
+ * `collection` resolves against).
31
+ */
32
+ export interface Principal {
33
+ id: string;
34
+ attributes?: Record<string, unknown>;
35
+ env?: Record<string, unknown>;
36
+ }
37
+ /** A principal, or just its id (shorthand for `{ id }`). */
38
+ export type PrincipalInput = Principal | string;
39
+ /**
40
+ * Derive a {@link Principal} from a (already verified) PCActn: the acting identity is the LEAF
41
+ * capability holder — the key the action was ultimately delegated to. Pass `opts.id` to map that
42
+ * holder key to the identity your policy is keyed on (e.g. an OpenFGA `user:alice`); it defaults to
43
+ * the raw leaf-holder key. Throws on a PCActn with no capability chain (a malformed / unverified
44
+ * object), rather than silently producing an empty principal.
45
+ */
46
+ export declare function principalFromPCActn(p: Pick<PCActn, 'cap_chain'>, opts?: {
47
+ id?: string;
48
+ attributes?: Record<string, unknown>;
49
+ env?: Record<string, unknown>;
50
+ }): Principal;
51
+ /** One ACL entry: the principal must hold `relation` on `object` (an OpenFGA relation check). */
52
+ export interface DocAcl {
53
+ relation: string;
54
+ object: string;
55
+ }
56
+ /**
57
+ * The minimal document shape the default extractor understands: a stable `id`, plus ACL metadata as
58
+ * an `acl` entry (single or list) and/or `relation:object` tag strings. A document needs AT LEAST ONE
59
+ * decidable ACL entry (via `acl` or `tags`) to be admissible — one with none fails closed.
60
+ */
61
+ export interface AclDocument {
62
+ id: string;
63
+ acl?: DocAcl | DocAcl[];
64
+ tags?: string[];
65
+ [k: string]: unknown;
66
+ }
67
+ /** Collect ACL entries from freeform `acl` + `tags` metadata (both `unknown`; proto-safe narrowing). */
68
+ export declare function aclsFromMetadata(acl: unknown, tags: unknown): DocAcl[];
69
+ /**
70
+ * A policy for the filter. One of:
71
+ * - a bare `Predicate[]` (raw PCA permits);
72
+ * - `{ openfga: { model, tuples } }` — an OpenFGA/Zanzibar authorization model + relationship
73
+ * tuples, compiled via {@link openfgaToPca} (relation closures — computedUserset, union,
74
+ * intersection, difference, tupleToUserset — are resolved into concrete permits);
75
+ * - `{ predicates, denies?, report? }` — an envelope-shaped result (e.g. a bridge `BridgeResult`),
76
+ * where `denies` is applied with deny-overrides-permit semantics.
77
+ */
78
+ export type PolicyInput = Predicate[] | {
79
+ openfga: {
80
+ model: unknown;
81
+ tuples: unknown;
82
+ };
83
+ } | {
84
+ predicates: Predicate[];
85
+ denies?: Predicate[];
86
+ report?: TranslationReport;
87
+ };
88
+ /**
89
+ * A compiled policy: a permit list, a deny list and whether the source translation was INCOMPLETE
90
+ * (a non-empty `report.errors` — in which case the whole policy fails closed and nothing is admitted).
91
+ * Compile once with {@link compilePolicy} and reuse across retrievals to avoid recompiling per call.
92
+ */
93
+ export interface CompiledPolicy {
94
+ readonly predicates: Predicate[];
95
+ readonly denies: Predicate[];
96
+ readonly incomplete: boolean;
97
+ readonly report?: TranslationReport;
98
+ }
99
+ /** Compile any {@link PolicyInput} (or pass through an already-{@link CompiledPolicy}). */
100
+ export declare function compilePolicy(policy: PolicyInput | CompiledPolicy): CompiledPolicy;
101
+ /** Per-document decision — the auditable record of why one candidate passed or was dropped. */
102
+ export interface DocDecision {
103
+ id: string;
104
+ allowed: boolean;
105
+ /** The ACL entry that granted access (present only when `allowed`). */
106
+ via?: DocAcl;
107
+ /** The exact permit predicate that matched (proof: which grant authorized this document). */
108
+ matched?: Predicate;
109
+ /** Human-readable reason — the fail-closed cause for a drop, or the grant for an allow. */
110
+ reason: string;
111
+ }
112
+ /**
113
+ * The full decision for a filter run — suitable to attach to a PCA proof / receipt. `digest` is a
114
+ * content-addressed commitment to the decision (principal + the admitted/dropped id sets), so a
115
+ * verifier can confirm the model was handed exactly these documents and no others.
116
+ */
117
+ export interface FilterDecision {
118
+ principal: string;
119
+ considered: number;
120
+ /** IDs admitted (the model may see these), in candidate order. */
121
+ allowedIds: string[];
122
+ /** IDs dropped (not authorized / unknown — fail closed), in candidate order. */
123
+ droppedIds: string[];
124
+ /** One record per candidate. */
125
+ decisions: DocDecision[];
126
+ /** True when the policy translation was incomplete → every candidate fails closed. */
127
+ policyIncomplete: boolean;
128
+ /** The policy-translation report, when the policy was imported (OpenFGA). */
129
+ report?: TranslationReport;
130
+ /** b64u content-address of this decision set (binds into the proof trace). */
131
+ digest: string;
132
+ }
133
+ /** Result of {@link filterDocuments}: the admitted documents plus the {@link FilterDecision}. */
134
+ export interface FilterResult<D> {
135
+ documents: D[];
136
+ decision: FilterDecision;
137
+ }
138
+ /** Options controlling how ACL metadata is read from a document. */
139
+ export interface FilterOptions<D extends AclDocument> {
140
+ /** Stable id for a document (default: `doc.id`, else a positional `doc#<index>`). */
141
+ getId?: (doc: D, index: number) => string;
142
+ /** ACL entries for a document (default: `doc.acl` + `relation:object` `doc.tags`). */
143
+ getAcls?: (doc: D) => DocAcl[];
144
+ }
145
+ /**
146
+ * Filter a candidate set to the documents `principal` may see under `policy`. Returns the admitted
147
+ * documents (in candidate order) and a {@link FilterDecision} proof trace. FAILS CLOSED: a document
148
+ * is admitted only when a permit predicate cleanly matches one of its ACL entries and no deny matches;
149
+ * anything unknown is dropped.
150
+ */
151
+ export declare function filterDocuments<D extends AclDocument>(principal: PrincipalInput, candidates: D[], policy: PolicyInput | CompiledPolicy, opts?: FilterOptions<D>): FilterResult<D>;
152
+ /** A generic retriever: returns candidate documents for a query. */
153
+ export interface RagRetriever<D extends AclDocument = AclDocument> {
154
+ retrieve(query: string, k?: number): Promise<D[]> | D[];
155
+ }
156
+ /** A retriever whose results are PCA-filtered before they reach the model. */
157
+ export interface FilteredRetriever<D extends AclDocument = AclDocument> {
158
+ retrieve(query: string, k?: number): Promise<D[]>;
159
+ /** The decision from the most recent `retrieve` (the proof trace), or `undefined` if none yet. */
160
+ lastDecision(): FilterDecision | undefined;
161
+ }
162
+ /**
163
+ * Wrap a generic {@link RagRetriever} so every result set is filtered to what `principal` may see
164
+ * BEFORE it reaches the model. The wrapper exposes the same `retrieve` plus `lastDecision()` for audit.
165
+ */
166
+ export declare function withPcaFilter<D extends AclDocument>(retriever: RagRetriever<D>, principal: PrincipalInput, policy: PolicyInput | CompiledPolicy, opts?: FilterOptions<D>): FilteredRetriever<D>;
167
+ /** Minimal structural shape of a LangChain `Document` (we never import `@langchain/*`). */
168
+ export interface LangChainDocumentLike {
169
+ pageContent: string;
170
+ metadata?: Record<string, unknown>;
171
+ }
172
+ /** Minimal structural shape of a LangChain retriever (`invoke` or the older `getRelevantDocuments`). */
173
+ export interface LangChainRetrieverLike<D extends LangChainDocumentLike = LangChainDocumentLike> {
174
+ invoke?(input: string): Promise<D[]> | D[];
175
+ getRelevantDocuments?(query: string): Promise<D[]> | D[];
176
+ }
177
+ /** How to read ACL metadata off a LangChain document (defaults read `metadata.acl` + `metadata.tags`). */
178
+ export interface LangChainAdapterOptions<D extends LangChainDocumentLike = LangChainDocumentLike> {
179
+ getId?: (doc: D, index: number) => string;
180
+ getAcls?: (doc: D) => DocAcl[];
181
+ }
182
+ /** A LangChain-shaped retriever whose results are PCA-filtered post-retrieval. */
183
+ export interface FilteredLangChainRetriever<D extends LangChainDocumentLike = LangChainDocumentLike> {
184
+ invoke(input: string): Promise<D[]>;
185
+ getRelevantDocuments(query: string): Promise<D[]>;
186
+ lastDecision(): FilterDecision | undefined;
187
+ }
188
+ /**
189
+ * Wrap a LangChain-shaped retriever. Results are filtered post-retrieval (before they reach the
190
+ * model); ACLs are read from each document's `metadata` by default. The underlying retriever is
191
+ * called via `invoke` when present, else `getRelevantDocuments`.
192
+ */
193
+ export declare function withLangChainPcaFilter<D extends LangChainDocumentLike>(retriever: LangChainRetrieverLike<D>, principal: PrincipalInput, policy: PolicyInput | CompiledPolicy, opts?: LangChainAdapterOptions<D>): FilteredLangChainRetriever<D>;
194
+ /** Minimal structural shape of a LlamaIndex node. */
195
+ export interface LlamaIndexNodeLike {
196
+ id_?: string;
197
+ metadata?: Record<string, unknown>;
198
+ }
199
+ /** Minimal structural shape of a LlamaIndex `NodeWithScore`. */
200
+ export interface LlamaIndexNodeWithScoreLike<N extends LlamaIndexNodeLike = LlamaIndexNodeLike> {
201
+ node: N;
202
+ score?: number;
203
+ }
204
+ /** Minimal structural shape of a LlamaIndex retriever. */
205
+ export interface LlamaIndexRetrieverLike<N extends LlamaIndexNodeLike = LlamaIndexNodeLike> {
206
+ retrieve(params: {
207
+ query: string;
208
+ } | string): Promise<Array<LlamaIndexNodeWithScoreLike<N>>> | Array<LlamaIndexNodeWithScoreLike<N>>;
209
+ }
210
+ /** How to read ACL metadata off a LlamaIndex node (defaults read `node.metadata.acl` + `.tags`). */
211
+ export interface LlamaIndexAdapterOptions<N extends LlamaIndexNodeLike = LlamaIndexNodeLike> {
212
+ getId?: (item: LlamaIndexNodeWithScoreLike<N>, index: number) => string;
213
+ getAcls?: (item: LlamaIndexNodeWithScoreLike<N>) => DocAcl[];
214
+ }
215
+ /** A LlamaIndex-shaped retriever whose results are PCA-filtered post-retrieval. */
216
+ export interface FilteredLlamaIndexRetriever<N extends LlamaIndexNodeLike = LlamaIndexNodeLike> {
217
+ retrieve(params: {
218
+ query: string;
219
+ } | string): Promise<Array<LlamaIndexNodeWithScoreLike<N>>>;
220
+ lastDecision(): FilterDecision | undefined;
221
+ }
222
+ /**
223
+ * Wrap a LlamaIndex-shaped retriever. The returned `NodeWithScore[]` is filtered post-retrieval
224
+ * (before it reaches the model); ACLs are read from each node's `metadata` by default.
225
+ */
226
+ export declare function withLlamaIndexPcaFilter<N extends LlamaIndexNodeLike>(retriever: LlamaIndexRetrieverLike<N>, principal: PrincipalInput, policy: PolicyInput | CompiledPolicy, opts?: LlamaIndexAdapterOptions<N>): FilteredLlamaIndexRetriever<N>;
package/dist/index.js ADDED
@@ -0,0 +1,307 @@
1
+ "use strict";
2
+ /**
3
+ * @atlasauth/pca-rag — FGA-for-RAG.
4
+ *
5
+ * Retrieval-time, per-principal document filtering driven by the PCA policy engine. Given a
6
+ * principal (or a verified PCActn's holder), a candidate set of documents that each carry ACL
7
+ * metadata (a `{ relation, object }` ACL entry, or `relation:object` tags), and a policy (raw PCA
8
+ * predicates, or an imported OpenFGA/Zanzibar ReBAC model+tuples), this returns ONLY the documents
9
+ * the principal may see — deciding every candidate through the core evaluator / `member_of` relation
10
+ * closure in `@atlasauth/pca`, and reusing `@atlasauth/pca-policy-bridge` to compile ReBAC relation
11
+ * checks into PCA predicates.
12
+ *
13
+ * Two properties make this suitable for the PCA proof trace:
14
+ * 1. FAIL CLOSED. A document is admitted ONLY when a permit predicate cleanly matches (verb =
15
+ * relation, resource = object, every `where` condition `true`) and no deny predicate matches.
16
+ * Anything unknown — no ACL, an unresolved relation, a malformed document, an incomplete policy
17
+ * translation — drops the document. The model can never see an unauthorized chunk.
18
+ * 2. AUDITABLE. Every decision is captured in a {@link FilterDecision}: which documents passed,
19
+ * which were dropped and why, the exact permit predicate that authorized each one, and a
20
+ * content-addressed `digest` of the whole decision set that can be bound into a receipt / proof.
21
+ *
22
+ * Decisions use the SAME evaluator the adjudicator uses, so "what the retriever filtered" and "what
23
+ * the authority system would admit" cannot drift apart.
24
+ */
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.principalFromPCActn = principalFromPCActn;
27
+ exports.aclsFromMetadata = aclsFromMetadata;
28
+ exports.compilePolicy = compilePolicy;
29
+ exports.filterDocuments = filterDocuments;
30
+ exports.withPcaFilter = withPcaFilter;
31
+ exports.withLangChainPcaFilter = withLangChainPcaFilter;
32
+ exports.withLlamaIndexPcaFilter = withLlamaIndexPcaFilter;
33
+ const pca_1 = require("@atlasauth/pca");
34
+ const pca_policy_bridge_1 = require("@atlasauth/pca-policy-bridge");
35
+ function toPrincipal(p) {
36
+ return typeof p === 'string' ? { id: p } : p;
37
+ }
38
+ /**
39
+ * Derive a {@link Principal} from a (already verified) PCActn: the acting identity is the LEAF
40
+ * capability holder — the key the action was ultimately delegated to. Pass `opts.id` to map that
41
+ * holder key to the identity your policy is keyed on (e.g. an OpenFGA `user:alice`); it defaults to
42
+ * the raw leaf-holder key. Throws on a PCActn with no capability chain (a malformed / unverified
43
+ * object), rather than silently producing an empty principal.
44
+ */
45
+ function principalFromPCActn(p, opts) {
46
+ const chain = Array.isArray(p?.cap_chain) ? p.cap_chain : [];
47
+ const leaf = chain.at(-1);
48
+ if (!leaf || typeof leaf.holder !== 'string' || leaf.holder.length === 0) {
49
+ throw new TypeError('principalFromPCActn: PCActn has no leaf capability holder');
50
+ }
51
+ const principal = { id: opts?.id ?? leaf.holder };
52
+ if (opts?.attributes !== undefined)
53
+ principal.attributes = opts.attributes;
54
+ if (opts?.env !== undefined)
55
+ principal.env = opts.env;
56
+ return principal;
57
+ }
58
+ function isDocAcl(v) {
59
+ if (v === null || typeof v !== 'object')
60
+ return false;
61
+ const rel = v.relation;
62
+ const obj = v.object;
63
+ return typeof rel === 'string' && rel.length > 0 && typeof obj === 'string' && obj.length > 0;
64
+ }
65
+ function aclArray(acl) {
66
+ if (Array.isArray(acl))
67
+ return acl.filter(isDocAcl);
68
+ return isDocAcl(acl) ? [acl] : [];
69
+ }
70
+ /** A `relation:object` tag → an ACL entry. The split is at the FIRST ':' so an object id may itself
71
+ * contain ':' (e.g. `viewer:document:readme` → relation `viewer`, object `document:readme`). */
72
+ function tagToAcl(tag) {
73
+ if (typeof tag !== 'string')
74
+ return null;
75
+ const i = tag.indexOf(':');
76
+ if (i <= 0 || i >= tag.length - 1)
77
+ return null;
78
+ return { relation: tag.slice(0, i), object: tag.slice(i + 1) };
79
+ }
80
+ /** Collect ACL entries from freeform `acl` + `tags` metadata (both `unknown`; proto-safe narrowing). */
81
+ function aclsFromMetadata(acl, tags) {
82
+ const out = aclArray(acl);
83
+ if (Array.isArray(tags)) {
84
+ for (const t of tags) {
85
+ const a = tagToAcl(t);
86
+ if (a !== null)
87
+ out.push(a);
88
+ }
89
+ }
90
+ return out;
91
+ }
92
+ function isCompiledPolicy(p) {
93
+ return (p !== null &&
94
+ typeof p === 'object' &&
95
+ !Array.isArray(p) &&
96
+ 'incomplete' in p &&
97
+ typeof p.incomplete === 'boolean');
98
+ }
99
+ /** Compile any {@link PolicyInput} (or pass through an already-{@link CompiledPolicy}). */
100
+ function compilePolicy(policy) {
101
+ if (isCompiledPolicy(policy))
102
+ return policy;
103
+ if (Array.isArray(policy))
104
+ return { predicates: policy, denies: [], incomplete: false };
105
+ if ('openfga' in policy) {
106
+ const br = (0, pca_policy_bridge_1.openfgaToPca)(policy.openfga.model, policy.openfga.tuples);
107
+ return {
108
+ predicates: br.predicates,
109
+ denies: br.denies,
110
+ report: br.report,
111
+ incomplete: br.report.errors.length > 0,
112
+ };
113
+ }
114
+ const predicates = Array.isArray(policy.predicates) ? policy.predicates : [];
115
+ const denies = Array.isArray(policy.denies) ? policy.denies : [];
116
+ const report = policy.report;
117
+ return { predicates, denies, report, incomplete: report !== undefined && report.errors.length > 0 };
118
+ }
119
+ /** Build the evaluation context for checking ONE ACL entry for a principal. */
120
+ function buildContext(principal, acl) {
121
+ const subject = { ...(principal.attributes ?? {}), id: principal.id };
122
+ const ctx = {
123
+ action: { verb: acl.relation, resource: acl.object },
124
+ subject,
125
+ };
126
+ if (principal.env !== undefined)
127
+ ctx.env = principal.env;
128
+ return ctx;
129
+ }
130
+ /** Decide a single document. Returns the per-document record; `allowed` governs admission. */
131
+ function decideDocument(id, acls, principal, compiled) {
132
+ if (compiled.incomplete) {
133
+ return { id, allowed: false, reason: 'policy translation incomplete (fail closed)' };
134
+ }
135
+ if (acls.length === 0) {
136
+ return { id, allowed: false, reason: 'no decidable ACL metadata (fail closed)' };
137
+ }
138
+ let lastReason = 'no relation grants access (fail closed)';
139
+ for (const acl of acls) {
140
+ let res;
141
+ try {
142
+ res = (0, pca_policy_bridge_1.decide)({ predicates: compiled.predicates, denies: compiled.denies }, buildContext(principal, acl));
143
+ }
144
+ catch {
145
+ lastReason = 'evaluator error (fail closed)';
146
+ continue;
147
+ }
148
+ if (res.allowed) {
149
+ const d = {
150
+ id,
151
+ allowed: true,
152
+ via: acl,
153
+ reason: `granted: ${principal.id} has ${acl.relation} on ${acl.object}`,
154
+ };
155
+ if (res.matched !== undefined)
156
+ d.matched = res.matched;
157
+ return d;
158
+ }
159
+ if (res.reason !== undefined)
160
+ lastReason = res.reason;
161
+ }
162
+ return { id, allowed: false, reason: lastReason };
163
+ }
164
+ function runFilter(principalInput, candidates, policyInput, ex) {
165
+ const principal = toPrincipal(principalInput);
166
+ const compiled = compilePolicy(policyInput);
167
+ const list = Array.isArray(candidates) ? candidates : [];
168
+ const documents = [];
169
+ const decisions = [];
170
+ const allowedIds = [];
171
+ const droppedIds = [];
172
+ for (let i = 0; i < list.length; i++) {
173
+ const doc = list[i];
174
+ let id;
175
+ let acls;
176
+ try {
177
+ id = ex.id(doc, i);
178
+ acls = ex.acls(doc);
179
+ }
180
+ catch {
181
+ // A document whose metadata cannot even be read is unknown → fail closed.
182
+ const fid = `doc#${i}`;
183
+ decisions.push({ id: fid, allowed: false, reason: 'unreadable document metadata (fail closed)' });
184
+ droppedIds.push(fid);
185
+ continue;
186
+ }
187
+ if (typeof id !== 'string' || id.length === 0)
188
+ id = `doc#${i}`;
189
+ const decision = decideDocument(id, acls, principal, compiled);
190
+ decisions.push(decision);
191
+ if (decision.allowed) {
192
+ documents.push(doc);
193
+ allowedIds.push(id);
194
+ }
195
+ else {
196
+ droppedIds.push(id);
197
+ }
198
+ }
199
+ const base = {
200
+ principal: principal.id,
201
+ considered: list.length,
202
+ allowedIds,
203
+ droppedIds,
204
+ policyIncomplete: compiled.incomplete,
205
+ };
206
+ const digest = (0, pca_1.hashCanonical)({ v: 1, kind: 'pca-rag/filter', ...base });
207
+ const decision = { ...base, decisions, digest };
208
+ if (compiled.report !== undefined)
209
+ decision.report = compiled.report;
210
+ return { documents, decision };
211
+ }
212
+ /**
213
+ * Filter a candidate set to the documents `principal` may see under `policy`. Returns the admitted
214
+ * documents (in candidate order) and a {@link FilterDecision} proof trace. FAILS CLOSED: a document
215
+ * is admitted only when a permit predicate cleanly matches one of its ACL entries and no deny matches;
216
+ * anything unknown is dropped.
217
+ */
218
+ function filterDocuments(principal, candidates, policy, opts) {
219
+ const ex = {
220
+ id: opts?.getId ?? ((doc) => doc.id),
221
+ acls: opts?.getAcls ?? ((doc) => aclsFromMetadata(doc.acl, doc.tags)),
222
+ };
223
+ return runFilter(principal, candidates, policy, ex);
224
+ }
225
+ /**
226
+ * Wrap a generic {@link RagRetriever} so every result set is filtered to what `principal` may see
227
+ * BEFORE it reaches the model. The wrapper exposes the same `retrieve` plus `lastDecision()` for audit.
228
+ */
229
+ function withPcaFilter(retriever, principal, policy, opts) {
230
+ const compiled = compilePolicy(policy);
231
+ let last;
232
+ return {
233
+ async retrieve(query, k) {
234
+ const docs = await retriever.retrieve(query, k);
235
+ const res = filterDocuments(principal, Array.isArray(docs) ? docs : [], compiled, opts);
236
+ last = res.decision;
237
+ return res.documents;
238
+ },
239
+ lastDecision() {
240
+ return last;
241
+ },
242
+ };
243
+ }
244
+ // ---- framework-shaped adapters (structural, optional-peer; no heavy deps imported) ---------------
245
+ function metaString(meta, key) {
246
+ if (meta === undefined || meta === null)
247
+ return undefined;
248
+ const v = meta[key];
249
+ return typeof v === 'string' && v.length > 0 ? v : undefined;
250
+ }
251
+ /**
252
+ * Wrap a LangChain-shaped retriever. Results are filtered post-retrieval (before they reach the
253
+ * model); ACLs are read from each document's `metadata` by default. The underlying retriever is
254
+ * called via `invoke` when present, else `getRelevantDocuments`.
255
+ */
256
+ function withLangChainPcaFilter(retriever, principal, policy, opts) {
257
+ const compiled = compilePolicy(policy);
258
+ let last;
259
+ const ex = {
260
+ id: opts?.getId ?? ((doc, i) => metaString(doc.metadata, 'id') ?? metaString(doc.metadata, 'source') ?? `doc#${i}`),
261
+ acls: opts?.getAcls ?? ((doc) => aclsFromMetadata(doc.metadata?.['acl'], doc.metadata?.['tags'])),
262
+ };
263
+ const fetch = async (input) => {
264
+ if (typeof retriever.invoke === 'function')
265
+ return await retriever.invoke(input);
266
+ if (typeof retriever.getRelevantDocuments === 'function')
267
+ return await retriever.getRelevantDocuments(input);
268
+ throw new TypeError('withLangChainPcaFilter: retriever has neither invoke nor getRelevantDocuments');
269
+ };
270
+ const run = async (input) => {
271
+ const docs = await fetch(input);
272
+ const res = runFilter(principal, Array.isArray(docs) ? docs : [], compiled, ex);
273
+ last = res.decision;
274
+ return res.documents;
275
+ };
276
+ return {
277
+ invoke: run,
278
+ getRelevantDocuments: run,
279
+ lastDecision: () => last,
280
+ };
281
+ }
282
+ /**
283
+ * Wrap a LlamaIndex-shaped retriever. The returned `NodeWithScore[]` is filtered post-retrieval
284
+ * (before it reaches the model); ACLs are read from each node's `metadata` by default.
285
+ */
286
+ function withLlamaIndexPcaFilter(retriever, principal, policy, opts) {
287
+ const compiled = compilePolicy(policy);
288
+ let last;
289
+ const ex = {
290
+ id: opts?.getId ??
291
+ ((item, i) => (typeof item.node?.id_ === 'string' && item.node.id_.length > 0 ? item.node.id_ : undefined) ??
292
+ metaString(item.node?.metadata, 'id') ??
293
+ `node#${i}`),
294
+ acls: opts?.getAcls ??
295
+ ((item) => aclsFromMetadata(item.node?.metadata?.['acl'], item.node?.metadata?.['tags'])),
296
+ };
297
+ return {
298
+ async retrieve(params) {
299
+ const items = await retriever.retrieve(params);
300
+ const res = runFilter(principal, Array.isArray(items) ? items : [], compiled, ex);
301
+ last = res.decision;
302
+ return res.documents;
303
+ },
304
+ lastDecision: () => last,
305
+ };
306
+ }
307
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,58 @@
1
1
  {
2
2
  "name": "@atlasauth/pca-rag",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "0.2.0",
4
+ "description": "FGA-for-RAG for PCA: retrieval-time, per-principal document filtering driven by the PCA policy engine, with the filtering decision captured in the proof trace (provable: the model only saw authorized data).",
5
+ "keywords": [
6
+ "rag",
7
+ "retrieval",
8
+ "document filtering",
9
+ "fine-grained authorization",
10
+ "agent authorization",
11
+ "proof-carrying authority",
12
+ "pca",
13
+ "ai agents"
14
+ ],
15
+ "license": "MIT",
16
+ "homepage": "https://github.com/Atlas-Authorization/pca#readme",
17
+ "bugs": {
18
+ "url": "https://github.com/Atlas-Authorization/pca/issues"
19
+ },
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "git+https://github.com/Atlas-Authorization/pca.git",
23
+ "directory": "packages/pca-rag"
24
+ },
25
+ "main": "./dist/index.js",
26
+ "types": "./dist/index.d.ts",
27
+ "exports": {
28
+ ".": {
29
+ "types": "./dist/index.d.ts",
30
+ "default": "./dist/index.js"
31
+ },
32
+ "./package.json": "./package.json"
33
+ },
34
+ "dependencies": {
35
+ "@atlasauth/pca": "0.2.0",
36
+ "@atlasauth/pca-policy-bridge": "0.2.0"
37
+ },
38
+ "devDependencies": {
39
+ "typescript": "^5.6.3",
40
+ "vitest": "^2.1.4"
41
+ },
42
+ "files": [
43
+ "dist",
44
+ "README.md",
45
+ "LICENSE"
46
+ ],
47
+ "engines": {
48
+ "node": ">=20"
49
+ },
50
+ "publishConfig": {
51
+ "access": "public"
52
+ },
53
+ "scripts": {
54
+ "build": "tsc -p tsconfig.build.json",
55
+ "typecheck": "tsc -p tsconfig.json --noEmit",
56
+ "test": "vitest run"
57
+ }
6
58
  }