BUILDZN / WORK
Permission aware knowledge search
Apply current source permissions inside the pgvector query before returning document chunks.

Synthetic data. This is a portfolio implementation with recorded command line runs. No customer data, paid model calls or hosting deployment were used.
Tests and demos use a deterministic mock provider. A Claude adapter sits behind the same interface; its live quality remains unmeasured.
Problem
A search result can disclose restricted content even if its source link is hidden later. Retrieval needs to enforce source access before ranking and before a model receives context.
Architecture
1. Normalize mock sources
Drive, Slack and Notion-style connectors store source nodes, folder relationships, user/group grants and revocable link capabilities.
2. Separate content and access
Versioned content chunks have local hash embeddings. Source ACLs and group membership remain live metadata, separate from the index.
3. Filter inside SQL
A recursive ancestry and ACL predicate runs inside PostgreSQL before pgvector ranking and LIMIT. Revoked, deleted and stale content is excluded.
4. Answer from permitted chunks
Only retrieved chunks reach the answer provider. A user with no accessible evidence gets an empty result without a model invocation.
Tradeoffs
- The query predicate is the authorization boundary. This is not RLS protection against callers with direct database credentials.
- 64-dimensional hash vectors are a small lexical baseline with collisions, not production semantic embeddings.
Test results
24 distinct test cases passed in at least one appropriate environment. Zero failures in the linked CI run.
| Environment | Passed | Skipped |
|---|---|---|
| Native PostgreSQL | 24 | 0 |
| Embedded PostgreSQL | 24 | 0 |
No test cases were skipped in either environment.
Leak suite: 1,728 synthetic user/query pairs across access changes, zero unauthorized chunks. Five-query retrieval evaluation: recall@3 1.0 and MRR 1.0.
Docker Compose built and ran the seeded demo from a fresh Actions checkout. These fixture measurements do not establish production accuracy, security certification or business outcomes.
Verified code: 88b632a9606d4042c304839780e8179cc747d726
Recorded demo output
Real stdout from the Docker demo in the linked CI run. All records, identities and messages are synthetic.
All documents, users and ACLs are synthetic.
Bob before revoke: [ 'deploy', 'leave-policy' ]
Bob after revoke: [ 'leave-policy' ]
Outsider restricted prompt: { text: 'No accessible evidence.', chunks: [] }
Carol refund evidence: {
text: '[refund-policy] Refund policy: delivered orders can receive refunds within thirty days, maximum fifty dollars.',
chunks: [
{
id: 'refund-policy:0',
node: 'refund-policy',
body: 'Refund policy: delivered orders can receive refunds within thirty days, maximum fifty dollars.',
distance: 0.6077677297236319
}
]
}Read the recorded output in the repository ↗Known limits
- Mock source-access changes are synchronous. Real connector event delays and permission semantics are outside this implementation.
- Revocation cannot retract context already sent to a model.
- The quality evaluation has five synthetic topical queries. Live Claude answer quality remains unmeasured.