How SCIM and Veza OAA can reshape SecurityV0's data model
SecurityV0's execution-path-tracing architecture already captures the core insight that identity security requires graph-level reasoning, but it currently lacks two capabilities that SCIM and OAA deliver out of the box: canonical permission normalization across systems and computed effective permissions via graph traversal. Adopting OAA's authorization schema as SecurityV0's connector normalization interface (NormalizedGraph) would close the most critical gaps, while a read-only SCIM endpoint would unlock integration with the IGA and PAM ecosystem. Neither specification alone is sufficient — OAA models authorization but not ownership decay or credential hygiene, while SCIM models identity lifecycle but not permissions at all. The right strategy is a layered adoption: OAA-inspired schema internally, SCIM-compatible API externally, and SecurityV0's unique temporal tracking and execution path concepts preserved as proprietary extensions.
OAA's entity model maps cleanly to SecurityV0 but reveals three blind spots
Veza's OAA defines a graph topology of Application → Local Users/Groups/Roles → Permissions → Resources/Sub-resources, with IdP identities correlated via email or principal name. Mapping this to SecurityV0 is mostly straightforward:
| SecurityV0 Entity | OAA Equivalent | Notes |
|---|---|---|
| Identity (service_principal, oauth_app, etc.) | Local User | OAA's identities field links local users to IdP entities; SecurityV0's finer-grained identity subtypes (PAT, github_app, agent) have no OAA equivalent and would need custom properties |
| Owner (human, team, business_unit) | No equivalent | OAA does not model ownership hierarchies — this is SecurityV0's most distinctive concept |
| Role | Local Role | Direct 1:1 mapping; OAA roles contain permission lists and support resource scoping |
| Permission | Permission (dual-layer) | OAA adds canonical CRUD mapping (DataRead, DataWrite, etc.) that SecurityV0 lacks |
| Resource | Resource + Sub-resource | OAA supports unlimited sub-resource nesting with permission inheritance flags |
| Credential | No equivalent | OAA does not model secrets, tokens, or credential rotation |
| — | Application | OAA groups all entities under an Application container — SecurityV0 lacks this |
Three gaps emerge. First, OAA's Application entity provides a top-level grouping that SecurityV0's model omits. When SecurityV0 ingests data from GitHub, Entra ID, and AWS, each source system should be a first-class Application node that groups its local identities, roles, and resources — exactly as OAA does with application_type (the vendor) and name (the instance). This enables cross-instance queries like "show all GitHub users with write access across all GitHub organizations." Second, OAA's sub-resource hierarchy with permission inheritance (apply_to_sub_resources flag) is absent from SecurityV0. A GitHub Organization → Repository → Branch hierarchy, or an AWS Account → S3 Bucket → Object hierarchy, would materialize naturally as OAA sub-resources. Third, SecurityV0 has no concept of canonical permissions — OAA's 10-type CRUD normalization (DataRead/Write/Create/Delete, MetadataRead/Write/Create/Delete, NonData, Uncategorized) allows cross-system queries like "who has DataDelete on any production resource" that SecurityV0 cannot currently express.
Conversely, SecurityV0 has concepts OAA entirely lacks: the Owner entity with decay tracking, the Credential entity with rotation status, and temporal versioning with drift detection. These should be modeled as custom properties or entirely new entity types in any OAA-inspired schema adoption.
SCIM's extension mechanism can normalize NHI entities but not their permissions
SCIM's core schema (RFC 7643) defines User and Group resources with a flexible extension mechanism using URI-namespaced attribute blocks. For SecurityV0's NHI-centric use case, SCIM offers three adaptation paths.
The first path uses the userType attribute, which RFC 7643 defines as accepting any string value (not just "Employee" or "Contractor"). SecurityV0 could set userType to "service_principal", "oauth_app", "github_app", "pat", "agent", or "machine_account" to distinguish non-human identities within the standard User schema. This approach is simple but loses type-specific attributes.
The second and more powerful path uses custom schema extensions. A SecurityV0-specific extension could carry NHI-relevant attributes:
{
"schemas": [
"urn:ietf:params:scim:schemas:core:2.0:User",
"urn:securityv0:scim:schemas:extension:nhi:1.0"
],
"userName": "ci-deploy-bot",
"userType": "service_principal",
"active": true,
"urn:securityv0:scim:schemas:extension:nhi:1.0": {
"credentialType": "oauth_client_credentials",
"ownerIdentity": "platform-team@corp.com",
"ownershipDecayScore": 0.73,
"lastCredentialRotation": "2025-11-15T10:30:00Z",
"executionPathCount": 14,
"scopeDriftDetected": true
}
}
The third path defines entirely new SCIM resource types — /ServicePrincipals, /Agents, /Credentials — each with purpose-built schemas and their own endpoints. RFC 7643 Section 3.2 explicitly permits this. Okta already defines /Roles and /Entitlements as custom resource types, and the expired PAM extension (draft-grizzle-scim-pam-ext) defined Container, PrivilegedData, and permission resource types that CyberArk and Delinea implemented in production.
The critical limitation: SCIM explicitly declares authorization modeling out of scope. RFC 7643 Section 4.2 states: "no explicit authorization model is defined... these are considered out of scope." The roles and entitlements attributes on User are opaque string lists with no defined semantics — they cannot express what a role grants, which resources it applies to, or how permissions inherit. An active IETF draft (draft-ietf-scim-roles-entitlements, October 2025) promotes Roles and Entitlements to first-class resources with hierarchy support (containedBy/contains), but still does not model permission-to-resource mappings. For SecurityV0's execution path tracing, SCIM provides the identity normalization layer but OAA or a Zanzibar-style model must handle authorization.
OAA treats authorization as graph edges where SecurityV0 uses embedded documents
The architectural divergence between OAA and SecurityV0 is fundamental. OAA constructs an Authorization Metadata Graph where identities, groups, roles, permissions, and resources are discrete nodes connected by typed edges. Veza computes effective permissions by traversing all paths from an identity node through intermediate nodes to resource nodes, expanding group memberships and resolving role assignments along the way. This graph is the primary query surface — Veza's search, governance workflows, alerts, and reports all query it.
SecurityV0 stores relationships as embedded references within MongoDB entity documents (OWNED_BY, HAS_ROLE, GRANTS, etc.) and materializes execution paths (Identity → Role → Permission → Resource) as pre-computed documents. This approach trades query flexibility for read performance: materialized paths are fast to scan but expensive to recompute when relationships change, and they cannot express queries the materialization didn't anticipate.
OAA's graph-first approach provides three capabilities SecurityV0's embedded model lacks:
Effective permission computation on demand. OAA resolves the transitive closure of all permission chains dynamically. If a user belongs to Group A, which has Role B, which contains Permission C that applies to Resource D and all its sub-resources — OAA computes this in real time. SecurityV0 would need to pre-compute and store every possible path, which becomes combinatorially expensive as the graph grows.
Canonical cross-system permission queries. Because every OAA permission maps to canonical CRUD types, Veza can answer "who has DataDelete across all systems" with a single graph traversal. SecurityV0's current model stores system-specific permission names without normalization, making cross-system queries require connector-specific logic.
Bidirectional traversal. OAA's graph supports both forward queries ("what can identity X access?") and reverse queries ("who can access resource Y?") with equal efficiency. SecurityV0's materialized paths are optimized for forward traversal (identity → resource) but reverse queries require scanning all paths. This matters directly for SecurityV0's core use case: tracing which identities have execution paths to a compromised resource requires efficient reverse traversal.
The practical recommendation is not to abandon MongoDB but to add a graph index layer (potentially using MongoDB's $graphLookup aggregation or an external graph database) that models authorization edges as first-class relationships and computes effective permissions via traversal rather than pre-materialization.
A dual-schema connector normalization strategy using both OAA and SCIM
SecurityV0's connector framework normalizes data from Entra ID, ServiceNow, GitHub, and AWS into a unified model. Both SCIM and OAA offer standardized schemas that could replace or augment the current NormalizedGraph interface, but they serve different layers:
SCIM as the identity normalization layer. Every connector should output SCIM-compatible User and Group objects for identity entities. This provides: standard attribute names (userName, displayName, active, emails), the externalId field for cross-system identity correlation, the meta attribute for basic versioning (created, lastModified, version), and the groups attribute with direct/indirect type discriminators. Custom NHI extensions carry SecurityV0-specific attributes. The SCIM schema's self-describing nature (discoverable via /Schemas and /ResourceTypes endpoints) means new connectors can declare their schemas programmatically.
OAA as the authorization normalization layer. Each connector should produce OAA-compatible JSON payloads describing: the Application (the source system instance), Local Users/Groups/Roles within that application, Permissions with canonical CRUD mappings, and Resources with sub-resource hierarchies. OAA's identity_to_permissions binding structure explicitly captures who has what permissions on what resources — exactly the data SecurityV0 needs to construct execution paths.
The combined normalization interface would look like:
Connector Output = {
identity_layer: SCIM User[] + Group[], // who exists
authorization_layer: OAA Application { // who can do what
local_users, local_groups, local_roles,
permissions (with canonical mapping),
resources (with sub-resources),
identity_to_permissions bindings
},
securityv0_extensions: { // what SecurityV0 uniquely tracks
credentials, ownership_chains,
temporal_metadata, drift_signals
}
}
This approach lets SecurityV0 leverage two well-documented schemas while preserving its unique capabilities. New connector developers get clear, industry-standard schemas to target rather than a proprietary format. SailPoint's "Transforms" pipeline — 18+ primitive normalization operations including ISO 3166 conversion, regex replacement, and lookup tables — offers a proven model for the transformation step between raw source data and normalized schema output.
What SecurityV0's connector SDK can learn from OAA's three-job pattern
Veza's OAA connector architecture defines a simple, elegant pattern: every connector has exactly three jobs — pull authorization data from the target system, transform it into OAA's JSON schema, and push the payload to Veza via REST API. The push model means Veza never needs credentials to the target system (only the connector does), the connector runs on the customer's infrastructure, and updates happen on the connector's schedule.
SecurityV0's connector SDK should adopt several OAA patterns:
Typed template classes. OAA's Python SDK (oaaclient) provides CustomApplication, CustomIdPProvider, and OAAPermission classes that guide developers through constructing valid payloads. Methods like add_local_user(), add_resource(), resource.add_sub_resource(), and user.add_permission() enforce schema correctness at development time rather than at ingestion time. SecurityV0 should provide equivalent typed builders for its entity types.
Canonical permission mapping as a required step. OAA forces connector developers to map every custom permission to canonical CRUD types. This is the single most impactful pattern SecurityV0 could adopt — it transforms connector development from "dump whatever the source system reports" to "classify every permission into a standard vocabulary." The 10-type canonical set (DataRead/Write/Create/Delete, MetadataRead/Write/Create/Delete, NonData, Uncategorized) is well-designed and could be adopted directly.
Community connector repository. Veza's MIT-licensed oaa-community GitHub repository contains production-quality connectors for GitHub, GitLab, Jira, Slack, Salesforce, and others. SecurityV0 should maintain a similar open repository to accelerate ecosystem growth.
Size and encoding constraints. OAA specifies practical limits: 100MB max payload, 512 characters for names/IDs, 4096 for other strings, UTF-8 required. These constraints prevent connector bugs from producing pathological payloads. SecurityV0's SDK should define similar guardrails.
One key difference: OAA connectors push full snapshots (with optional incremental updates), while SecurityV0's event-sourcing architecture might prefer a stream of change events. The SDK should support both patterns — full snapshot for initial ingestion and periodic reconciliation, and incremental events for real-time drift detection.
Six concepts SCIM and OAA introduce that SecurityV0 currently lacks
Canonical permission normalization. OAA's dual-layer model — raw permissions ("Admin", "Operator", "merge") mapped to canonical CRUD types — is the most impactful missing concept. Without it, SecurityV0 cannot answer cross-system queries about effective access levels. Every connector currently outputs system-specific permission names with no common vocabulary.
Computed effective permissions. SecurityV0 materializes execution paths but does not compute the transitive closure of all permission chains through group memberships, role inheritance, and cross-system identity correlation. OAA computes this via graph traversal, producing a flattened view of what each identity can actually do. For SecurityV0's drift detection, comparing effective permissions over time would surface scope drift far more precisely than comparing raw role assignments.
Sub-resource hierarchies with inheritance flags. OAA's apply_to_sub_resources boolean on each permission definition controls whether permissions propagate down resource hierarchies. SecurityV0's flat Resource entity cannot express that "admin on a GitHub Organization implies admin on all its repositories" without explicit duplication. Adding hierarchical resources with configurable inheritance would dramatically reduce data volume while improving accuracy.
Application-level entity grouping. OAA's Application entity groups all identities, roles, and resources belonging to a single system instance. SecurityV0 currently tags entities with source system metadata but does not model the source system itself as a first-class entity. This prevents queries like "show all applications where a specific identity type has excessive permissions."
Permission scoping by resource type. OAA permissions can be restricted to specific resource types via the resource_types array. A "read" permission might apply only to "repository" resources, not "organization" resources. SecurityV0's Permission entity has no resource-type scoping.
HRIS correlation. OAA's Custom HRIS Provider template links employees to IdP identities via matching email, id, or idp_id fields. This enables SecurityV0 to trace ownership from a service principal → local user → IdP user → HRIS employee → manager/department — exactly the chain needed to detect ownership decay when an employee changes roles or departs.
SCIM endpoints would unlock IGA and PAM integration but not SIEM
If SecurityV0 exposed a read-only SCIM 2.0 API, it would become consumable by a significant ecosystem of security tools — but the value varies dramatically by category.
IGA platforms (high value). SailPoint, Saviynt, and ConductorOne all consume SCIM data for identity governance. A SCIM endpoint would allow these platforms to ingest SecurityV0's discovered NHI inventory for access certification campaigns, role mining, and compliance reporting. Given that NHIs outnumber human identities 92:1 to 144:1 (Entro Labs 2025 data) and 80% of identity-related breaches involve NHIs (CSA 2024), IGA platforms are actively seeking NHI data sources. SecurityV0 could serve as the discovery layer that feeds IGA governance workflows.
PAM tools (medium value). CyberArk, BeyondTrust, and StrongDM support SCIM for identity sync. BeyondTrust Password Safe uses SCIM to identify privileged accounts within its directory. SecurityV0 could push discovered service principals and machine accounts to PAM tools via SCIM for vault enrollment. The expired PAM SCIM extension (draft-grizzle-scim-pam-ext) — implemented by CyberArk and Delinea — defined resource types for privileged data and container permissions that align with SecurityV0's credential tracking.
SIEM platforms (low value via SCIM). SIEMs do not consume identity data via SCIM. Microsoft Sentinel uses native Entra ID integration, Splunk uses its Assets and Identity Framework with LDAP/AD connectors, and Chronicle uses direct API integrations. For SIEM integration, SecurityV0 should expose event logs via syslog or HTTPS (drift detection events, new execution path discoveries, ownership decay alerts) rather than SCIM endpoints.
OAA-compatible API (strategic value). Exposing an OAA-compatible payload API would enable Veza customers to ingest SecurityV0's execution path data directly into Veza's Authorization Graph. This is strategically valuable because Veza is the leading commercial platform for authorization graph analytics, and SecurityV0's unique NHI ownership-decay data would enrich Veza's graph with temporal signals it currently lacks.
A read-only SCIM implementation is straightforward: implement GET on /Users, /Groups, and discovery endpoints (/ServiceProviderConfig, /ResourceTypes, /Schemas), return HTTP 501 for write operations, support filtering (filter=userType eq "service_principal" and active eq true), and declare the read-only posture in ServiceProviderConfig. SCIM's built-in meta.version (ETag-based) aligns naturally with SecurityV0's versioned entities.
Real-world authorization graph implementations validate this architectural direction
Production implementations confirm that the graph-first approach to authorization modeling delivers measurable results. Choice Hotels used Veza's authorization graph to understand the link between Okta identities and multiple AWS accounts across 14 hotel brands — a cross-system correlation problem structurally identical to SecurityV0's execution path tracing. Snowflake used Veza to optimize RBAC and reduce identity-based risk in their Data Cloud. ConductorOne built a "Unified Identity Graph" with 300+ connectors covering SCIM and non-SCIM applications alike.
The Zanzibar lineage — Google's tuple-based authorization system — has spawned production-grade open-source implementations. OpenFGA (CNCF Incubating, Auth0/Okta) handles 1 million requests per second with 100 billion relationship tuples at millisecond latency. SpiceDB (AuthZed) achieves 5ms p95 with contributions from GitHub and Netflix. Both systems model authorization as (subject, relation, object) tuples with schema-defined inheritance — a pattern SecurityV0 could adopt for its execution path representation. The execution path Identity → Role → Permission → Resource maps directly to a chain of Zanzibar tuples: (identity, has_role, role), (role, grants, permission), (permission, applies_to, resource).
For effective permissions computation at scale, Neo4j case studies demonstrate that fine-grained, property-free relationship types perform nearly 2x faster than coarse-grained relationships with properties — a finding relevant to SecurityV0's MongoDB-based graph modeling. Amazon Neptune's hybrid pattern — graph database as source of truth synced to a ReBAC system for real-time checks — offers an architecture that could complement SecurityV0's MongoDB store with a purpose-built authorization index.
Conclusion: a three-layer adoption strategy
The analysis reveals that SecurityV0 should adopt SCIM and OAA not as replacements but as three complementary layers addressing distinct architectural needs.
Layer 1 — Internal schema (OAA-inspired). Adopt OAA's entity taxonomy (Application, Local Users/Groups/Roles, Permissions with canonical CRUD mapping, Resources with sub-resource hierarchies) as SecurityV0's NormalizedGraph schema. Extend it with SecurityV0-unique entities: Owner (with decay tracking), Credential (with rotation status), and temporal metadata. This is the highest-impact change — it introduces canonical permissions and computed effective permissions while preserving SecurityV0's distinctive capabilities.
Layer 2 — Connector interface (dual SCIM + OAA). Define the connector SDK output as SCIM-compatible identity objects plus OAA-compatible authorization payloads. This gives connector developers two well-documented, industry-standard schemas to target. Enforce canonical permission mapping as a required step, following OAA's pattern.
Layer 3 — External API (SCIM read-only + OAA export). Expose a read-only SCIM endpoint for IGA/PAM integration and an OAA-compatible export for authorization graph platforms. Ship event streams via syslog/HTTPS for SIEM integration. This positions SecurityV0 as both a consumer and producer in the identity security ecosystem.
The most novel finding: no existing specification models ownership decay or temporal drift — SecurityV0's core differentiator. SCIM tracks created and lastModified timestamps. OAA preserves graph snapshots for time-travel queries. But neither tracks the dynamic relationship between an autonomous identity's expanding execution paths and its decaying human ownership chain. This gap confirms that SecurityV0's temporal tracking and drift detection should remain proprietary extensions layered on top of standardized schemas, not constrained by them.
Next Action
Status: adopted — shipped
Findings incorporated into docs/architecture/01-data-model.md, 05-connectors.md, and associated ADRs. No further action required.