14 KiB
Enterprise Access-Control Integration
Date: 2026-05-04
Purpose
This note explains how Markitect's access-control gateway should integrate with enterprise IAM while respecting the local NetKingdom/key-cape direction.
The answer is yes: trust zones and access groups can map to canonical directory group membership, but Markitect should not trust raw AD group names directly. The enterprise shape should be:
OIDC/SAML/SCIM identity and directory plane
-> canonical subject claims
-> policy map and/or policy decision point
-> Markitect policy gateway
-> filtered document/query/context results
Markitect is the policy enforcement point for Markdown knowledge results. It should validate and normalize identity data through adapters, then call a policy decision point through the existing policy interfaces.
Canonical Enterprise Shape
The canonical enterprise pattern is the PEP/PDP/PIP/PAP split:
| Component | Markitect fit |
|---|---|
| PEP: policy enforcement point | AccessPolicyGateway at query, search, context, workflow, export, and assisted-prompt boundaries. |
| PDP: policy decision point | Local label policy for development; OpenFGA/SpiceDB, OPA/Rego, Cedar, or enterprise authorization service through adapters. |
| PIP: policy information point | NetKingdom/key-cape OIDC claims, directory group resolution, object labels, backend metadata, workflow context, and environment attributes. |
| PAP: policy administration point | Enterprise IAM/policy administration, plus versioned Markitect mapping files for labels, actions, trust zones, and emergency rules. |
This keeps Markitect small and auditable. It enforces decisions where Markdown knowledge leaves a boundary, but it does not become the enterprise directory, SSO provider, or policy administration system.
Local Infrastructure Fit
The local canon already points the right way:
- NetKingdom SSO is the reference identity provider.
- Keycloak is the reference OIDC provider, with privacyIDEA-backed MFA.
- key-cape is the lightweight OIDC/profile-enforcement path for local, sandbox, and bootstrap scenarios.
- Services should trust OIDC tokens, validate issuer/audience/signature/expiry, and authorize from explicit roles/scopes.
Markitect should therefore consume the NetKingdom IAM profile rather than create its own identity standard.
Enterprise Reference Architecture
flowchart LR
AD["AD / LDAP / HRIS"] --> SCIM["SCIM / Directory Sync<br/>(PIP)"]
SCIM --> IdP["NetKingdom SSO<br/>Keycloak / key-cape-compatible OIDC"]
IdP --> Token["OIDC Access Token<br/>roles, scopes, groups, org, assurance"]
Token --> Mapper["Identity Claim Mapper"]
Mapper --> Subject["PolicySubject"]
Source["Markdown objects<br/>labels, paths, trust zones"] --> Object["PolicyObject"]
Subject --> Gateway["Markitect AccessPolicyGateway<br/>(PEP)"]
Object --> Gateway
Gateway --> PDP["Policy Decision Point<br/>local / OpenFGA / OPA / Cedar"]
PDP --> Decision["PolicyDecision + audit metadata"]
Decision --> Boundary["Filtered query/search/context results"]
Identity Plane
OIDC should be the default authentication path for users and services. SAML may remain relevant for enterprise federation, but Markitect should normalize both into the same subject shape.
The canonical accepted claims should follow the NetKingdom IAM profile:
isssubaudexpiatscopeorscppreferred_usernamerolesorrealm_access.roles- recommended
groups,azp,email,name
For humans, Authorization Code + PKCE is the right login flow. For services, client credentials or workload identity should produce short-lived service tokens. OAuth token exchange can support hub-to-hub delegation where a service acts on behalf of a user.
Directory And Group Plane
Enterprise directories remain authoritative for group membership. Provisioning should use a standard such as SCIM where possible; AD/LDAP synchronization into Keycloak is also reasonable when NetKingdom owns the identity plane.
Important design rule:
directory groups -> canonical roles/scopes/trust labels -> Markitect subject
Avoid:
raw AD group name -> direct Markitect privilege
Reasons:
- AD group names change and often encode organizational accidents.
- Token group claims can be too large for large organizations.
- Privilege should be expressed as app roles/scopes or an explicit mapping file.
- Group membership freshness must be visible in the decision trail.
For Microsoft Entra-style group claims, large tenants may hit token group overage. Markitect should therefore support a group-resolution adapter rather than assuming all groups are always present in the token.
Policy Plane
The existing Markitect interfaces already provide the main policy boundary:
AccessPolicyGateway.authorize(subject, action, object_id, context)
AccessPolicyGateway.filter_results(subject, action, results, context)
AccessPolicyGateway.explain_decision(decision_id)
The existing data models also fit enterprise needs:
PolicySubject: identity, roles, groups/labels, allowed actions, attributes.PolicyObject: path, labels, trust zone, attributes.PolicyDecision: stable decision id, effect, reason, labels, trust zone, metadata.PolicyFilterResult: filtered results, decisions, diagnostics, summary.
The adapter seams are also correct:
RelationshipPolicyAdapterfor OpenFGA/SpiceDB/Zanzibar-style checks.RulePolicyAdapterfor OPA/Rego, Cedar, or other ABAC engines.
This follow-up adds the missing interface layer:
OIDC token or SAML assertion -> verified EnterpriseIdentity -> PolicySubject
Concrete adapters must validate issuer, audience, expiry, signature, and assurance metadata before any authorization decision is made. The core package now exposes protocol/data boundaries for this without taking a dependency on Keycloak, Entra, LDAP, SCIM, OpenFGA, OPA, or Cedar client libraries.
The current Markitect-side implementation provides deterministic local building blocks:
NetKingdomIdentityClaimsAdaptervalidates required IAM-profile claims, issuer, audience, token timestamps, roles/scopes, and production rejection of local development issuers for already trusted claims or explicit JWT fixtures.EnterprisePolicyMapandLocalEnterprisePolicyMappermap groups, roles, and scopes intoPolicySubjectlabels, trust zones, actions, and diagnostic attributes.StaticDirectoryGroupResolvermodels group freshness and overage without a live directory dependency.FlexAuthResourceManifestdescribes Markitect knowledge resources for future flex-auth registration.LocalDecisionLogStoreprovides a JSONL development/test sink for decision records.
Live OIDC discovery, JWKS signature verification, directory synchronization, central policy administration, and durable enterprise audit should be provided by flex-auth/key-cape-facing adapters rather than Markitect core.
Canonical Subject Mapping
Recommended normalized shape:
subject:
id: "oidc:<issuer>#<sub>"
display_name: "Ada Lovelace"
principal_type: human | service
issuer: "https://sso.example.org/realms/netkingdom"
audience: ["markitect-tool"]
authorized_party: "markitect-cli"
roles: [viewer, operator]
scopes: [openid, profile, hub:read]
groups:
- /markitect/readers
- /platform/architecture
allowed_labels: [public, internal]
trust_zones: [public, internal]
assurance:
mfa: true
acr: "..."
amr: ["pwd", "otp"]
directory:
source: keycloak | entra | ldap | scim
refreshed_at: "2026-05-04T10:00:00Z"
The mapping file should translate enterprise groups and app roles to Markitect labels and actions:
id: markitect-enterprise-policy-map
issuer: https://sso.example.org/realms/netkingdom
audiences: [markitect-tool]
groups:
/markitect/readers:
allowed_labels: [public, internal]
actions: [query, search, read]
/markitect/stewards:
allowed_labels: [public, internal, restricted]
actions: [query, search, read, package, export]
roles:
admin:
allowed_labels: [public, internal, restricted]
actions: [query, search, read, package, export, policy-admin]
scopes:
markitect:read:
actions: [query, search, read]
trust_zones:
internal:
required_groups: [/markitect/readers]
Command-line subject mapping:
mkt policy subject examples/policy/netkingdom-claims.yaml \
--policy-map examples/policy/enterprise-policy-map.yaml
Data/Object Mapping
Markdown remains the source-friendly object labeling layer:
---
policy:
labels: [internal]
trust_zone: internal
owner: team:platform-architecture
---
A Markitect knowledge base can publish an explicit flex-auth resource manifest:
id: markitect-example-knowledge-base
system: markitect-tool
actions: [read, query, search, package, export]
resources:
- id: knowledge-base:markitect-example
type: knowledge_base
- id: document:internal-note
type: document
parent: knowledge-base:markitect-example
path: examples/policy/private/internal-note.md
labels: [internal]
trust_zone: internal
For enterprise environments, object metadata should eventually include:
- content labels/classification
- repository/path
- owning team or project
- business domain
- tenancy/org
- retention or export constraints
- provenance of label assignment
Path rules remain useful as a safety net, but document labels and backend metadata should become authoritative for cached/context-package retrieval.
Enforcement Points
Markitect should enforce policy at every point where knowledge leaves a boundary:
mkt cache querymkt search- context package creation and activation
- workflow outputs
- assisted/LLM prompt assembly
- export/render steps
- backend APIs or future MCP resources
The highest-risk point is context assembly for agents. Before WP-0008 turns context caches into agent memory, policy must be able to answer:
- who is activating the context package?
- which token or service account is acting?
- which labels/trust zones are included?
- was anything denied or redacted?
- can this package be reactivated later under the same policy assumptions?
Interface Confirmation
The WP-0009 infrastructure is a good foundation. It already has:
- policy gateway protocol
- local label gateway
- explainable decisions
- filter-before-return behavior
- query/search integration
- relationship and rule adapter boundaries
This follow-up adds these provider-neutral interfaces in
markitect_tool.policy.adapters:
-
IdentityClaimsAdapter- validates OIDC/JWT/SAML assertions
- normalizes NetKingdom/key-cape-compatible claims into
EnterpriseIdentity
-
DirectoryGroupResolver- resolves group overage or stale claims
- supports SCIM/Graph/LDAP/Keycloak admin APIs behind adapters
- records freshness and source provenance
-
EnterprisePolicyMapper- maps canonical groups, roles, scopes, and tenants to Markitect labels, trust zones, actions, and object constraints
-
DecisionLogStore- persists policy decisions for query/context/workflow runs
- records token hash, subject id, action, object id, policy version, result, reason, and redaction status
-
workflow/runtime policy injection
subject_from_tokenpolicy_maprequired_assuranceemergency_justification
Concrete implementations remain future work. This is deliberate: key-cape and NetKingdom should own identity issuance and profile compliance, while Markitect owns normalization, policy envelopes, diagnostics, and enforcement at knowledge boundaries.
Recommended Direction
Do not make AD/LDAP/Entra groups a Markitect core dependency.
Instead:
- Accept NetKingdom/key-cape-compatible OIDC tokens.
- Normalize claims into
PolicySubject. - Map enterprise groups/roles/scopes to Markitect labels/trust zones/actions.
- Use the existing
AccessPolicyGatewayas the enforcement point. - Let OpenFGA/SpiceDB/OPA/Cedar attach through adapter protocols where a deployment needs stronger central policy.
- Persist decisions before using this for production agent memory or exports.
flex-auth Boundary
The preferred long-term shape is a separate flex-auth service/repo under the
NetKingdom authorization umbrella. In that model, Markitect remains a resource
consumer and policy enforcement point. flex-auth owns the central resource
registry, enterprise group/role/scope mapping, external PDP adapters, and
durable decision logs.
The product survey, Keycloak/Entra analysis, and boundary recommendation now
live in the sibling flex-auth repo:
flex-auth/docs/flex-auth-authorization-registry-research.md.
Implementation follow-up is tracked there:
FLEX-WP-0002: standalone policy-as-code core and check APIs.FLEX-WP-0003: flex-auth service-side Markitect consumer integration.FLEX-WP-0004: delegated PDP and directory adapters.
Markitect should not implement a live flex-auth service client until
FLEX-WP-0003 stabilizes the resource-registration and check/batch_check API.
Sources
- OpenID Connect Core 1.0: https://openid.net/specs/openid-connect-core-1_0.html
- OAuth 2.0 Token Exchange, RFC 8693: https://www.rfc-editor.org/rfc/rfc8693
- SCIM Protocol, RFC 7644: https://datatracker.ietf.org/doc/rfc7644
- NIST SP 800-162 ABAC guide: https://csrc.nist.gov/pubs/sp/800/162/upd2/final
- NIST glossary, Policy Enforcement Point: https://csrc.nist.gov/glossary/term/policy_enforcement_point
- NIST glossary, Policy Decision Point: https://csrc.nist.gov/glossary/term/policy_decision_point
- NIST glossary, Policy Information Point: https://csrc.nist.gov/glossary/term/policy_information_point
- Keycloak Server Administration Guide: https://www.keycloak.org/docs/latest/server_admin/
- Microsoft Entra group claims: https://learn.microsoft.com/en-us/security/zero-trust/develop/configure-tokens-group-claims-app-roles
- OpenFGA concepts: https://openfga.dev/docs/concepts
- Open Policy Agent policy language: https://www.openpolicyagent.org/docs/policy-language
- Cedar policy language: https://docs.cedarpolicy.com/
- Local canon:
/home/worsch/the-custodian/canon/standards/iam-profile_v0.1.md