← Identity Fabric
Grayskull Technology · Lab Identity Governance Fabric · 4 / 5

Standards-Based Integration Architecture

what you'll learn: the two planes — provisioning (SCIM) and signaling (SSF/CAEP/RISC) — and how every system plugs in through open standards
What we're solving for

One identity truth governs both logical AND physical access, and everything integrates through open standards — not bespoke connectors. HRIS is the source of who-is-who; every downstream system (Duo, AD/Entra, apps, and the door) is granted through the same provisioning standard and re-evaluated through the same signaling standard. Add a system by speaking the standard, not by writing a one-off integration.

Two planes, two standards

Identity integration splits cleanly into a slow, stateful provisioning plane and a fast, event-driven signaling plane. Governance lives on the first; continuous, real-time reaction lives on the second. Every hook into the fabric uses one or both.

Plane 1 · Provisioning (state)

SCIM 2.0

The governed, slow path — establishes who has what. HRIS → IGA reconcile → ITSM change gate → grant/revoke on Duo, AD/Entra, and (new) the PACS. Inbound SCIM to IGA-Lite is already ITSM-gated; outbound writes are the Admin-API / directory legs.

RFC 7643/7644 · create · update · deactivate · delete
Plane 2 · Signaling (events)

SSF — OpenID Shared Signals

The real-time path — broadcasts what just changed. One transmitter, many receivers; each re-evaluates continuously. CAEP carries session/security events, RISC carries account lifecycle. This is the "everyone integrates the same way" layer.

SSF 1.0 · CAEP 1.0 (Final) · RISC · SET (secevent+jwt)
flowchart LR
  HRIS[HRIS-Lite\nsource of record] --> IGA[IGA-Lite\ngovernance / JML]
  REQ[Self-service\naccess request]:::req --> IGA
  CMDB[CMDB-Lite\nCI / device trust] -.enriches.-> IGA
  IGA -->|F3 · RFC| ITSM{ITSM-Lite\nchange gate}
  ITSM -->|Duo push · SG-CAB-Approvers RBAC\nserialized · SoD| CAB([CAB approver]):::cab
  CAB -->|approve / deny · F4| ITSM
  ITSM -->|SCIM / Admin API| DUO[Duo]
  ITSM -->|SCIM / LDAPS| AD[AD / Entra]
  ITSM -->|SCIM| PACS[PACS-Lite\nthe door]
  subgraph SIG[Signaling plane — SSF]
    TX[VIGIL SSF\ntransmitter]
  end
  IGA -->|lifecycle → RISC| TX
  IGA -->|grant applied → assurance-level-change| TX
  CMDB -->|posture → CAEP| TX
  TX -->|CAEP / RISC| DUO
  TX -->|CAEP / RISC| CII[CII / Oort]
  TX -->|CAEP / RISC| PACS
  TX -->|CAEP / RISC| APPS[Apps / RPs]
  PACS -.badge-in = presence.-> TX
  classDef req fill:#160f22,stroke:#3b3170,color:#e6edf3;
  classDef cab fill:#201a10,stroke:#a98f2a,color:#f0f6fc;
    
Provisioning grants access (blue path, ITSM-gated) — every grant is approved by a Duo push to a CAB approver resolved from the SG-CAB-Approvers AD group (serialized, SoD-routed). SSF broadcasts change to every receiver in real time (green plane); an applied grant emits a CAEP assurance-level-change. PACS is both a SCIM target and an SSF receiver — and a transmitter of presence.

The Change Approval Board — how the gate approves

The ITSM gate doesn't auto-approve grants — it requires a human CAB decision, authenticated by a Duo push. The push goes only to members of the SG-CAB-Approvers AD security group — the RBAC source of truth, resolved from AD and stamped into every RFC — so approver identity is governed, not hardcoded.

MechanismWhat it doesWhy
Duo-push approvala change in awaiting_approval sends an async Duo push; the approver's allow/deny on-device is the decision (F4)phishing-resistant, on-device CAB approval
SG-* RBACiga resolves SG-CAB-Approvers members → Duo usernames → RFC approvers[]; itsm pushes only to themwho-may-approve is an AD group, governed like any entitlement
Serialized pushesat most one push outstanding per approver; the next sends only after the current resolvesa multi-grant persona never fires simultaneous pushes (Duo anti-fraud)
SoD routinga privileged group grant routes as normal + SOD-PRIV, not the auto-approvable standardsegregation of duties on privileged access
Grant → SSFon an applied grant, iga fans a CAEP assurance-level-change to CII + PACSa posture increase re-evaluates downstream in real time

Requests arrive two ways — birthright (persona-derived) and self-service (the /request intake) — and both flow through the same gate: RFC → Duo-push CAB → approve → apply → assurance-level-change. Every decision lands on the tamper-evident audit spine and the Grafana Change Approval Board row.

Where SSF fits — and how

You already built the hard part. The VIGIL SSF/CAEP stack (transmitter :8001 · receiver :8002 · bridge :8003, SSF 1.0 / CAEP 1.0) is live on its own tunnel and verified interop with caep.dev and with CII/Oort (a real session-revoked push returned HTTP 202). The SCIM→RISC leg already maps lifecycle changes to RISC events. So SSF isn't something to add — it's the spine that turns the fabric from a set of point integrations into a broadcast bus.

The role each standard plays

LayerStandardCarriesFabric hookStatus
ProvisioningSCIM 2.0account/badge create·update·deactivate·deleteinbound → IGA (ITSM-gated); outbound → Duo/AD/PACSlive (inbound gated)
Session signalsSSF · CAEPsession-revoked · credential-change · assurance-level-change · device-compliance-changeVIGIL transmitter → receivers (Duo, CII, PACS, apps)verified (caep.dev + CII)
Lifecycle signalsSSF · RISCaccount-disabled · account-purged · account-enabled · identifier-changed/recycledIGA lifecycle → SCIM→RISC leg → transmitterbuilt (poll-diff reconciler)
Reader ↔ controllerOSDP + Secure Channelencrypted physical read (replaces clear-text Wiegand)PACS-Lite reader edge (P4 realism)roadmap
Mobile credentialAliro 1.0NFC/UWB wallet badge (CSA, Feb 2026)PACS-Lite credential issuanceroadmap
Badge enrollmentRFIDeas Universal Enroll SDKread card CSN / facility+ID (125 kHz prox · 13.56 MHz iCLASS/MiFare · mag-stripe)PACS-Lite enrollment reader (pcProx / WAVE ID) → bind badge to identitypersonal IP
Assurance scoringCIAF (VIGIL)continuous assurance score from the signal stream → adaptive decisionsthe bridge's CIAF seam (Voxiren IP, deferred)seam only

Lane: the SSF/CAEP stack is Personal/R&D (vigil-ssf-poc) — standards plumbing only. The patentable CIAF scoring core is Voxiren IP and stays deferred until IP assignment; it plugs into the one ciaf_seam boundary. Nothing here builds the scoring engine.

PACS as the fifth hook

Physical access is the last identity domain the fabric doesn't govern. Modern PACS (Verkada, Avigilon Alta, Brivo) now ship native SCIM + webhooks, so the door governs exactly like a Duo group — through the same two planes, three concrete hooks:

flowchart TB
  subgraph FABRIC[Lab Identity Governance Fabric]
    IGA2[IGA-Lite] --> ITSM2{ITSM gate}
    TX2[SSF transmitter]
  end
  ITSM2 -->|1 · SCIM target\nbadge granted on hire,\nrevoked on leaver| PACS2[PACS-Lite]
  TX2 -->|2 · SSF receiver\nrevoke on session-revoked /\naccount-disabled — instantly| PACS2
  PACS2 -->|3 · SSF transmitter\nbadge-in = presence signal| TX2
  TX2 -.assurance / impossible-travel\nbadge-in vs SSO login.-> RISK[CIAF assurance\nVoxiren · deferred]
    
One leaver kills logical AND physical access; a revoked session drops the badge in real time; a badge-in becomes a Zero-Trust signal. The badge-vs-SSO impossible-travel check no vendor ships turnkey is the CIAF differentiator.

Badge enrollment — RFIDeas Universal Enroll SDK

Before a badge can be governed it has to be bound to an identity. PACS-Lite enrolls the physical credential with the RFIDeas Universal Enroll SDK — an enrollment reader (pcProx / WAVE ID) reads the card's CSN (or iCLASS facility + ID) and PACS-Lite ties it to the worker, so the same JML that provisions the account also provisions the door.

Lane: PACS-Lite functionality, design, and integration/interoperability are personal IP (Voxiren) — the RFIDeas enrollment leg and the badge-vs-SSO impossible-travel signal are part of that IP; the CIAF assurance core stays deferred until IP assignment.

Adoption path (PACS-Lite POC)

PhaseBuildProves
P0mock badge-event feed → Splunk HEC → Grafana; PACS-Lite as a SCIM SP + SSF receiver stubthe door on the two planes, end-to-end, in software
P1~$15 ESP32 / ESP-RFID reader → Node-RED → HECreal hardware badge events
P2IGA-Lite reconciles the badge; ITSM gates it; SSF revoke wiredone leaver → logical + physical access gone
P3validate SCIM-from-Entra against Brivo dev sandbox / Verkada trialthe pattern holds against a real vendor API
P4OSDP + Aliro realismmodern physical-layer standards

Duo on the lab's AD — and how CII sees it

Open standards cover the new systems; the lab's legacy AD is covered by Duo's on-prem protection surfaces, and Cisco Identity Intelligence ingests AD directly.

SurfaceProtects / ingestsHow
Duo · Windows LogonInteractive console + RDP logonDuo Authentication for Windows Logon (credential provider)
Duo · Legacy AD ProtectionLegacy on-prem apps that auth via AD (Kerberos / NTLM)Sub-auth filter DLL on the DCs → Duo MFA (Push / phone) · fail-open configurable
Duo · Command-Line ProtectionRemote non-interactive: PS-Remoting · SSH · SFTPMFA on command-line logons (user must pre-exist in Duo)
CII · AD integrationAD users / groups / attributes · stale + guest · password hygieneLightweight PowerShell → SCIM to Cisco Identity Intelligence (no DC agent)

Windows Logon + Legacy AD + Command-Line Protection close the MFA gap across every AD logon path — interactive, legacy-app, and remote shell — while the CII AD ingest folds on-prem AD into the same identity-intelligence plane (Oort · Astrix · BHE) as cloud and SaaS.

Credential vaulting — 1Password, the lab's CyberArk

Governance decides who may hold a credential; a vault holds the secret itself and brokers every checkout. The lab runs 1Password as its PAM/vault tier — the same split CyberArk draws between PVWA (people) and CCP / AAM (machines):

User-front · human checkout

1Password vaults + op CLI

People retrieve elevated and break-glass credentials from a scoped 1Password vault — the CyberArk PVWA equivalent. Checkout is Duo-gated, per-vault access follows the tier model, and use is audited. The break-glass secret lives here dormant, not in a config file.

CastleOps vault · per-lane scopes · Duo-gated · audited retrieval
Machine storage · app-to-app

1Password Connect + Service Accounts

Services and CI fetch secrets programmatically from self-hosted 1Password Connect (the API the consoles already health-check) and Service Accounts — no secret in the image, none in git. This is the CyberArk CCP / AAM / Conjur equivalent: the machine authenticates, the vault releases only the secret it's entitled to.

op://CastleOps · Connect API · Service Accounts · secret-refs, not secrets
CyberArk workflow1Password equivalentFabric use
PVWA — human credential checkout1Password app + op CLIelevated / break-glass retrieval · Duo-gated · audited
CPM — rotation / managed accounts1Password item rotationservice-account secrets rotated in the vault, not hand-edited
CCP / AAM / Conjur — app-to-app1Password Connect + Service Accountsconsoles & CI fetch op:// refs at runtime — no secret in image/git

This closes the loop with the ownership model: a service account's identity is governed in the NHI registry while its secret is vaulted in 1Password — human-checkout for break-glass, machine-fetch via Connect for the account itself. Personal/CastleOps lane; secrets never land in the repo.

← Prev: Lifecycle & JML Hub Next: Agentic AI gateways & access →