Skip to content

Feature support

Feature support

Everything that is not a wire protocol. For the RFC-by-RFC record see Standards & conformance; for the grading vocabulary — Full, Partial, Contract only, Host-supplied, No — see Capabilities.

Identity & authentication

Capability Grade Notes
Global subjects with a pluggable user model Full The host's own User model is resolved through config; the package owns the schema.
Password authentication Full Framework hasher (bcrypt/argon2id), constant-time failure path, rehash-on-login.
Password policy — length, reuse history, expiry, lockout, MFA and SSO mandates Full An environment sets the floor; an organization may only tighten it, never negotiate below it. Minimum length defaults to 12. Reuse history and expiry default to off until you set them; lockout is on by default (10 failures in 15 minutes, see below).
Breached-password screening Contract only The shipped default answers "not breached" for every password. See the caveat in Standards.
Password complexity classes No
Bulk user import with lazy hash migration Full CSV or JSON via cbox-id:users:import; foreign hashes are refused unless you bind a verifier for the format, then upgraded to the platform hasher on first successful login.
Sessions — absolute TTL and idle timeout Full 8 hours and 30 minutes by default; amr recorded on the session.
"Remember me" persistent login No
Step-up / sudo re-authentication Partial / Host-supplied RFC 9470: access tokens and introspection carry acr and auth_time. AuthenticationRequirement checks a token or a session against acr_values/max_age, and BearerChallenge renders the insufficient_user_authentication challenge. Your resource server and your /authorize call them (Require step-up authentication). No sudo mode, and no route middleware.
TOTP second factor Partial SHA-1, 6 digits, 30 s, ±1 step — fixed. Secrets sealed at rest, replay blocked.
WebAuthn / passkeys Partial Real verification; ES256 and RS256 only; none and self-attested packed only. Inert until rp_id and origin are configured. Challenge issuance is host-supplied.
Recovery / backup codes Full
Magic-link email sign-in Full Hash-only single-use token with a TTL.
Password reset Full Hash-only single-use token, TTL, anti-enumeration, revokes every session on reset.
Email verification Full Hash-only single-use token, TTL, stale-address guard.
One-time passcodes (OTP) Partial Keyed HMAC at rest (HKDF subkey off the master key), decoy hash for uniform timing, per-recipient and per-IP rate limits, per-challenge attempt cap. Email and SMS channels ship — plus a log channel for development and a null channel.
SMS OTP Full SmsOtpChannel over Twilio, MessageBird, Bird or 46elks (HTTP, no SDK), E.164 normalisation, a toll-fraud guard (country allow-list, per-number cooldown and cap, per-IP cap, per-environment and deployment daily caps) and an audit row per send with the number masked. See Send one-time codes by SMS.
SMS second factor Full SmsFactors: enrol, challenge, remove; number sealed at rest; off by default per environment, with a country allow-list and "not an administrator's only factor". See Offer SMS as a second factor.
Voice / push OTP Contract only OtpChannel is the extension point.
Login lockout Full Serialized under a row lock, audited, and on by default since 1.22: 10 failures inside 15 minutes lock the subject for 15 minutes. A policy's lockoutThreshold overrides the default; cbox-id.lockout.* sets the default, the window and the duration (threshold: 0 turns the default off). The lock always expires on its own.
Federated sign-in and explicit account linking Full Provider-agnostic FederatedPrincipal. A federated identity is never merged into an existing account by email; that path is refused so linking stays deliberate. Each linked identity records when it last signed somebody in (identities.last_used_at), so an account page can show which links are still in use.
Named social providers (Google, GitHub, Microsoft buttons) Partial ProviderCatalog carries fifteen providers — Google, Microsoft Entra ID, Okta, Auth0, Keycloak, GitLab, Slack, GitHub, Discord, Apple, Facebook, LinkedIn, Bitbucket, Xero, Intuit — with issuers or endpoints, scopes, claim mapping and setup steps, and the OIDC and OAuth 2.0 clients that complete them. The sign-in page and its buttons are the host's. See Sign-in provider catalogue.
Enterprise IdP setup guides Full IdentityProviderGuides: twenty typed guides (SAML or OIDC, plus SCIM where the IdP can push to a custom app) mapping your values to each IdP's own field labels. Data only — the console is the host's. See Enterprise SSO setup guides.

Authorization

Capability Grade Notes
Roles and permissions, scoped per organization Full Uniqueness is per (organization, client_id, role name), so two apps can own a role of the same name.
Hierarchy-aware roll-down Full A role granted at an ancestor organization applies to its descendants, via a closure table.
Wildcard permissions (billing.*) No Permission matching is exact-name equality.
Role inherits role No Only organization hierarchy inherits; there is no role graph.
Relationship-based authorization (ReBAC) Partial A real tuple store with recursive userset expansion, cycle protection and a depth limit of 12. Not cached — every check is live queries, two per node. No policy DSL, and no compatibility with any external authorization-service wire protocol.
Policy decision point Partial The PDP decides from ReBAC tuples only. RBAC permission checks run on their own path and do not pass through it — treat them as two authorization systems that meet at the decision endpoint, not one.
Entitlements fed by your billing engine Full Version-tagged cache invalidation, environment-scoped keys, and a random re-seed on counter loss so a stale snapshot cannot resurrect. Never holds billing state.
Authorization decision endpoint (POST /oauth/decisions) Full Permission and entitlement checks in one round trip, batch capped (default 50) so one request cannot become an unbounded number of queries.
Entitlement claims embedded in the access token Full Coarse entitlements ride as an ent claim with a staleness signal; instant-critical ones stay live.
Feature flags (per user, per organization, percentage rollout) Full Environment-owned flags with a default and a kill switch; user rules outrank organization rules, which outrank a stable SHA-256 rollout bucket. Evaluated in memory from one cached set per environment, invalidated on every change. Delivered as a feature_flags claim behind the feature_flags scope and through FeatureFlags::evaluate(). No multivariate (non-boolean) flags, no scheduled changes, no rule on arbitrary attributes. See Feature flags.
Bring-your-own RBAC driver Contract only Switching the driver away from builtin binds stubs that refuse every call until you supply an adapter.
Group → role mapping from the directory Full SCIM group membership changes reconcile role assignments.
App-declared role manifests Full Apps publish their own roles/permissions over HTTP; fetching is SSRF-guarded and syncs hourly.
Staff roles (not tenant-assignable) Full tenant_assignable: false on a role; the tenant plane neither lists nor accepts it, directory mappings refuse it.
Environment-wide grants of one app's role Full Stamped only into that app's tokens; app-agnostic roles reach every app.
Support sessions (act as a user) Partial Code-flow sign-in as a member with act, no refresh, ≤ 60 min, audited on both sides. First-party, environment-owned apps only. The staff-facing UI and the app's handling of act are the host's.
XACML No

Organizations & tenancy

Capability Grade Notes
Environments as a hard identity boundary Full Own users, own keys, own issuer. Deny-by-default: no environment in context means zero rows.
Organizations, memberships, invitations Full Invitations are explicit-acceptance — creating one grants nothing. Last-owner removal is refused.
Reseller / parent hierarchy Full Closure table with loop-refusing subtree moves.
Groups and resource grants Full Both write ReBAC tuples.
Custom domains Partial DNS TXT challenge, verification, and promotion to issuer host. Deliberately TLS-agnostic — certificate issuance is yours.
Home-realm discovery (email domain → SSO connection) Partial The lookup primitive ships and is environment-scoped, but there is no endpoint and no caller — routing a login by email domain is yours to wire.
User API tokens Full Capped at the issuing member's role.
Customer API keys (POST /oauth/api-keys/verify) Full Bound to one app, org and holder; permissions capped at the holder's current permissions for the app at issuance AND re-capped at every verification; verified by the app with its own client credentials, uniform active: false otherwise.
Platform control plane — operators, accounts, projects Full Accounts sit above the environment boundary; account members are ordinary subjects in the platform-root environment rather than a second credential store. Signed, expiring, purpose-pinned handoff into a tenant environment.

Directory & provisioning

Capability Grade Notes
Inbound SCIM 2.0 server Partial Users and Groups with the full RFC 7644 filter grammar, sorting, ETags (If-Match / If-None-Match), /Bulk with bulkId references, and PATCH value-path filters; replays of the Microsoft Entra ID and Okta conformance requests are in the test suite. No /Me, no POST /.search, no changePassword. See Standards for the per-section detail and Connect Entra ID and Okta for setup.
Directory pull connectors Full Google Workspace (Admin SDK) and Microsoft Entra (Graph). Both normalise into the same value objects and run the same reconciliation as SCIM push. Neither is a SCIM client — they are proprietary REST APIs shaped into SCIM. Both carry a setup guide in the provider catalogue (ProviderCatalog::forDirectory()), so a console can render the same guidance for a directory that it renders for a sign-in connection.
HR-system (HRIS) directory sync Full Workday (RaaS report, integration user or OAuth refresh token), BambooHR, Rippling, HiBob and Personio (v2). Employment dates decide access (termination at the end of the last day, pre-hires from their start date), departments become groups, the manager becomes the enterprise manager attribute, chosen fields pass through as custom attributes. Incremental where the API filters by change (BambooHR, Rippling) between full pulls; per-record failures are reported, not fatal; a mass deprovisioning is refused. Setup guides in HrisCatalog.
Immediate deprovision Full Deactivation drops membership and revokes sessions immediately.
Erasure (GDPR Art. 17) Full SubjectEraser: one transaction removes credentials, sessions, grants, memberships, role grants and vault secrets, scrubs stored payloads, pseudonymises the subject row (id kept), emits user.erased (SCIM DELETE downstream) and returns a receipt. Hosts register steps for their own stores. The audit trail is not rewritten — past entries keep the opaque id; see erasure.
Outbound SCIM provisioning Partial A generic SCIM 2.0 client against any endpoint, with bearer or client-credentials auth, a durable outbox, retries, dead-lettering, per-connection circuit breaker, and a resolve-once IP-pinned SSRF guard. Users only — no group or membership push. No vendor-specific connectors.
Deprovision policy Full Per connection: deactivate (active: false) or delete.

Governance

Capability Grade Notes
Access-certification campaigns Full Snapshot, certify/revoke, apply on close. Revocations are genuinely applied, and a refusal (last owner, say) is recorded with its reason rather than dropped. Un-reviewed items default to revoke. Overdue campaigns close on a schedule.
Segregation of Duties Partial Pre-grant gate plus conflict scanning, with reasoned decisions. Ignores hierarchy-inherited roles.
Scope of both Partial RBAC role assignments (organization and environment-wide) and organization memberships only. Entitlements and ReBAC tuples are out of scope — ReBAC tuples have no enumeration surface to certify against.

Audit & observability

Capability Grade Notes
Append-only hash-chained audit trail Full SHA-256(canonical payload ‖ previous hash), one chain per environment and scope, with the environment id inside the hash so a row cannot be moved between environments undetected. Appends serialize on an anchor row and retry on unique-constraint collision.
Signed checkpoints Partial A JWS over {scope, up_to_sequence, root_hash} closes the tail-truncation hole that a bare chain leaves open. cbox-id:audit:checkpoint signs every advanced chain and can run daily on the scheduler — but the schedule ships off (audit.checkpoint.schedule, default false), because the first signature forecloses a planned one-time re-chain. Until you enable it or call for a checkpoint yourself, deletion of the chain's tail is not detectable.
Tamper-proof storage No This is tamper-evident, not tamper-proof: no WORM storage, no external notarization or transparency log, and no per-entry signature. Someone with database write access can still delete rows — the chain and checkpoints are what make it visible.
Audit query and SIEM pull stream Full Filtered, paginated reads plus a sequence cursor.
Outbound SIEM streaming Partial Transactional outbox committed with the audit entry, at-least-once, pumped every minute. One transport: HTTP(S). Splunk HEC, Elastic ECS, GELF 1.1, ArcSight CEF and generic JSON are five formats over it. No file, S3, syslog-transport or OCSF sink.
Retention / pruning Full cbox-id:prune sweeps ten tables with per-table defaults and a dry-run mode. audit_logs is deliberately never pruned — pruning below a checkpoint would break verification, and pruning up to one would remove the anchor.

Events, webhooks & hooks

Capability Grade Notes
Transactional outbox for domain events Full Emitted inside the caller's transaction, so a rolled-back change cannot leave an event behind.
Delivery guarantee Partial At-least-once, explicitly — subscribers must be idempotent. Exactly-once is neither claimed nor implemented.
Relay backlog observability Full Logged every pass, warns above a threshold, and cbox-id:events:backlog exits non-zero on demand for alerting.
Outbound webhooks Full Asynchronous, uniqueness-locked, exponential backoff to a 12-attempt dead letter, stranded-delivery rescue, per-endpoint circuit breaker, gap-free per-endpoint sequence, HTTPS-only DNS-pinned SSRF guard.
Webhook signature Full Per endpoint. Cbox (default): HMAC-SHA256 over "{timestamp}.{body}", sent as X-Cbox-Timestamp and X-Cbox-Signature: t=…,v1=… — not Standard Webhooks, so do not point a spec-compliant verifier at it. Standard Webhooks: webhook-id / webhook-timestamp / webhook-signature: v1,… over "{id}.{timestamp}.{body}" with a whsec_ secret, held to the specification's published vector. Only the chosen scheme's headers are sent. No secret rotation overlap window and no asymmetric v1a signatures. See verify webhook signatures.
Webhook replay protection Full The timestamp is signed, and both receiver-side verifiers (StandardWebhookSignature::verify(), CboxWebhookSignature::verify()) enforce a tolerance window in both directions (300 seconds by default). Deduplication is the receiver's: key it on webhook-id (Standard Webhooks) or the body's delivery_id.
Event catalog Full 28 typed event types plus a * wildcard subscription.
Inline hooks (external actions) Full Six points — token minting, post-login, pre/post registration, pre/post password change — each with its own fail policy (token_minting, pre_registration and pre_password_change fail closed). In-process handlers or signed, SSRF-guarded HTTP calls with pinned DNS and no redirects. A deny at a non-vetoable point is audited and folded to an allow rather than silently ignored.

Cryptography & secrets

Capability Grade Notes
Envelope encryption for secrets at rest Full XChaCha20-Poly1305-IETF (libsodium), random nonce per message, bound to a context string as AEAD additional data. Not AES-GCM.
Signing key management and rotation Full RSA-2048, P-256 or Ed25519; private keys sealed per-kid; cbox-id:keys:rotate with an Active→Rotating→Retired overlap so in-flight tokens keep verifying.
Master-key rotation Full Versioned keyring: each ciphertext names its key (a derived id, never the key); CBOX_ID_CRYPTO_PREVIOUS_KEYS keeps old keys for opening only; cbox-id:crypto:rewrap re-seals every registered column in resumable chunks (--dry-run); the doctor warns while anything is under a previous key. Pre-1.22 envelopes keep opening. See master key management.
HSM / KMS integration Contract only SecretBox is the swap point; no AWS KMS, Vault or PKCS#11 implementation ships.
Token vault for downstream credentials Full Seals third-party credentials and brokers short-lived, deny-by-default leases to clients. Uniform refusal with no enumeration oracle; the real reason goes to the audit log only. Per-grant TTL can only shorten the default. Secret rotation is supported, and vault secrets are re-sealed by a master-key rotation like every other sealed column.

Operations & tooling

Capability Grade Notes
Artisan commands Full Fifteen, including cbox-id:install, cbox-id:doctor, cbox-id:users:import, cbox-id:directory:sync, cbox-id:provisioning:sync, cbox-id:keys:rotate, cbox-id:events:relay, cbox-id:events:backlog, cbox-id:prune, cbox-id:audit:checkpoint, cbox-id:audit-streams:pump, cbox-id:governance:close-overdue.
Scheduled work Full Manifest sync, audit-stream pump, governance auto-close and the event relay all register themselves, config-gated and withoutOverlapping. See Operations — the platform delivers nothing without a queue worker and scheduler running.
Usage metering Full Per-day, per-environment, per-organization counters fed off the outbox, with a reconciler for drift. Metering never enforces — enforcement belongs to entitlements.
Testing helpers Full Every module ships InteractsWith* traits and fakes, and the package's own suite uses them.
Database engines Partial SQLite, MySQL 8.0.13+, PostgreSQL 14+ and MariaDB 10.2+ are green in CI — genuinely, since the engines job moved to a runner where it can reach its service containers. SQL Server has never been run. See Requirements — that page is the authority, not this row.
Telemetry / metrics runtime No Deliberate: a library must not force an observability stack on its host.
Admin console, hosted login, consent screen Host-supplied This package is UI-free.

Client SDKs

First-party client libraries wrap sign-in, the profile/account redirect, back-channel token exchange, webhook-signature verification, the Token Vault and app-manifest publishing. They are separate packages — installing cboxdk/laravel-id does not install them, and their own repositories are the authority on what they support.

SDK Package
JavaScript / TypeScript @cboxdk/id-js
React @cboxdk/id-react
Vue / Nuxt @cboxdk/id-vue, @cboxdk/id-nuxt
Python (unpublished — source only)
Go github.com/cboxdk/id-go
Laravel / PHP cboxdk/laravel-id-client