Roadmap: External ACL Inheritance and Permission-Aware Retrieval

Gap statement: Wikantik enforces its own ACLs well, but cannot inherit anyone else's

Wikantik's page ACLs are enforced on every retrieval surface — the bundle's candidate retrieval, the format filter, and the ontology's public/restricted materialization split. What it lacks is the enterprise-defining capability: inheriting permissions from connected source systems so that a document synced from Confluence or Drive is only retrievable by users who could see it at the source. Without connectors this gap is moot; with them (RoadmapConnectorFramework) it becomes the enterprise gate.

Market grounding: permission sync is the monetized enterprise feature

That last point is the strategic opening: Wikantik already runs the exact substrate (PostgreSQL + pgvector) the recommended architecture calls for, while vector-DB-based competitors have to bolt authorization on. This can be done better here, not just at parity.

Current Wikantik state

Proposed direction

  1. Principal mapping: map external principals (source-system users/groups) onto wiki principals, keyed by the identities SCIM/SSO already provision — a source_principals mapping table plus group expansion.
  2. ACL sidecar per derived page: connectors write source ACL references at sync time; a resolver translates them into wiki-visible allow-lists on the derived page.
  3. In-database enforcement: push the permission predicate into the pgvector query (WHERE on a permissions join) and into a Lucene filter clause for the BM25/HNSW paths — pre-filtering, never post-filtering.
  4. Evaluate externalized policy (Cedar/Oso-style policy-as-code) as a later layer over the existing JAAS + policy_grants model, not a replacement.

Phase 1 scope and acceptance criteria

First session scope: the source_principals migration + ACL-sidecar schema + a resolver mapping ONE connector type's source ACL refs to wiki principals. Enforcement wiring comes after the resolver's semantics survive design review.

Phase 1 (enforcement) is done when these tests are green — all run under a restricted PostgreSQL role, never a superuser (established project finding: permission bugs escape superuser CI):

  1. A user without source-side access to a restricted derived page gets zero sections/results from it on all three surfaces — /api/bundle, search, and the knowledge MCP tools — one test per surface, plus proof the exclusion happened by index-level pre-filter (inspect the query, not just the output).
  2. Fail-closed: an unresolvable external principal, or a missing/stale ACL sidecar, denies access — with a test asserting deny, not a fallback to public.
  3. A permission change at the source is reflected after the next sync, and the sync lag is observable (surfaced as a freshness/drift metric, not silent).
  4. A user with legitimate access still retrieves the page (no over-blocking regression), and overall recall@12 on the eval corpus does not regress for unrestricted content.

Verify before designing on these

Non-goals

Investigation starting points

See Also