← Simplexable Services

Implementation notes

Platform X and Simplexable Services

Technical source for integrating @simplexable/services-platform-client@0.1.0. A Platform X delegates centralized user and group authority to Services and retains ownership of application and domain behavior.

§1 Purpose — ownership boundaries

“Owns” means that party is the only authority that may establish, mutate, or invalidate the fact. The other party may consume a projection of the fact but MUST NOT invent, rewrite, or co-author it. There is no supported hybrid or co-authoritative identity model.

Services owns

  • Centralized identity (users and groups as Services-defined facts)
  • Authoritative group/user state and the group SSoT revision
  • Authentication and session establishment
  • Actor-token issuance and validation
  • Platform-X deployment registration and group binding
  • Machine credentials (digest-only persistence)
  • Determination of whether a committed change is revision-worthy
  • Post-commit refresh notification to the registered Platform X endpoint
  • Registration/connection truth for the group’s dataset (host, database, port, role, password)

Platform X owns

  • Application and domain behavior
  • Local authorization policy that decides whether a human may ask Services to mutate Services-owned identity
  • Local SSoT projection / repository and how the application uses it
  • Application-specific configuration
  • Its refresh HTTP endpoint
  • Reactions after a refreshed identity snapshot is adopted (cache invalidation, websocket fan-out, UI refresh, and so on)

§2 Architectural model

2.1 Runtime relationship

After login/handoff, Platform X clients ordinarily talk only to the Platform X backend. The Platform X backend talks to Services when Services authority is required. Browsers MUST NOT become Services API clients.

Browser
   |
Platform X frontend
   |
Platform X backend
   |-- Services auth/handoff: /users/login-password, /users/login-key,
   |   /users/validate-handoff  (not the SSoT contract)
   |
   +-- Services /external/v1  (machine SSoT, connection, actor mutations)

2.5 Notification-driven refresh

Services notifies only after commit, and only when the change is revision-worthy. Notification failure MUST NOT roll back committed Services state.

Services authoritative change
   |
COMMIT
   |
post-commit refresh notification
   |
Platform X refresh endpoint
   |
SSoT repository reread
   |
local adoption
   |
Platform X consumers

How Platform X works

These are separate concerns (per the web extraction guide). Do not collapse them into a single “Services client” story.

Human login / handoff (§2.2, §11 step 4)

Current auth uses /users/login-password, /users/login-key, and /users/validate-handoff until an external-v1 auth contract exists. Not a SSoT fallback. The Platform X backend receives actorToken and MUST keep it server-side only.

Machine authentication (§3.A, §6)

Backend-only px1 credential for /external/v1:

Authorization: Bearer px1.<credentialId>.<secret>

Human actor authority (§3.B, §11 step 3)

Actor JWT is backend-only; required for actor-authorized mutations and GET /session; fail closed if missing. Persistence is host policy.

X-Services-Actor: Bearer <actor JWT>

Authoritative SSoT (§2.3, §7)

Services owns users/groups and the revision. Platform X adopts a projection via conditional GET (ETag / If-None-Match). The package repository adopts a higher revision, refuses regression, and fail-closes on empty cache plus transport/auth failure.

Refresh notification (§2.5, §9)

After commit, Services POSTs to the registered refresh URL. Body is exactly { "target": "<opaque target>" } (see §9). Platform X validates Bearer auth, matches opaque target, rereads SSoT.

Secure installation (§12–§16)

Provisioner stdout → installer stdin; protected env 0600; no secret argv; --check / --install / --verify. Pin @simplexable/services-platform-client@0.1.0 from the npm registry (not file:).

§3 Trust and credential model

Three credentials. They are not interchangeable.

Credential Header / use Direction
Platform machine credential Authorization: Bearer px1.… Platform X → Services /external/v1
Services actor token X-Services-Actor: Bearer … Platform X → Services (mutations, GET /session)
Refresh notification secret Authorization: Bearer … on refresh POST Services → Platform X

Refresh-notification secrets MUST NOT authenticate /external/v1. Target HMAC is addressing, not authentication. A leaked machine credential must not forge refresh doorbells; a leaked refresh secret must not call /external/v1.

§7 SSoT contract

Canonical DTOs

On-the-wire shapes (Platform X MAY remap field names locally):

ServicesGroup  { id, name, active }
ServicesUser   { id, groupId, email, name, level, active }
ServicesActor  { userId, groupId, level, active, sessionId,
                 userAuthorityVersion, groupAuthorityVersion }

Revision and ETag

  • Scope: one groupId.
  • Existing/new groups initialize at revision 1.
  • ETag: "group-ssot:{groupId}:{revision}" (literal form: group-ssot:{groupId}:{revision}).
  • Conditional GET: If-None-Match equality → 304.
  • “CURRENT” is established only by successful SSoT reread (or 304 against an existing snapshot), not by notification alone.

Notification is not data

Notification means only: reread the Services users/groups SSoT for this target. It MUST NOT carry users, group name, revision, or mutation type.

§8 Mutation contract

machine authority
+ human actor authority
+ Idempotency-Key
+ If-Match revision (visible-state mutations)

Services validates machine and actor, applies If-Match where required, mutates authoritative state, increments group SSoT revision once when the change is revision-worthy, persists idempotency in the same transaction, COMMITs, then notifies after commit if revision-worthy.

Revision-worthy: group name change; user create; visible user profile change (name, email, level); user deactivate / reactivate.

Not revision-worthy: password-only change; no-op updates; registration / connection / api_token / api_url / server_timezone changes.

Package: identity.updateGroup, createUser, updateUser, deactivateUser, reactivateUser send If-Match from expectedRevision. identity.setUserPassword sends expectedUserAuthorityVersion (no If-Match).

§9 Refresh notification contract

POST <refresh-url>
Authorization: Bearer <notificationAuthSecret>
Content-Type: application/json

{ "target": "<opaque target>" }

Target derivation:

target = HMAC-SHA256(key = notificationTargetKey,
                     data = lowercase(trim(groupId)))
         as base64url

Receiver (createServicesRefreshHandler): auth mismatch → 401; invalid body → 400; zero local group matches → 200 generic success; more than one match → 500 fail-closed; exactly one match → invoke refreshGroup(groupId), then 200. Platform X MUST reread SSoT after a matched notification.

§10 Package integration

Install exactly @simplexable/services-platform-client@0.1.0 from the npm registry. Backend only. Node engines: ^24.18.0 || >=26.0.0. The package sets "browser": false.

Export Responsibility
createServicesClient HTTPS client for /external/v1 (machine auth, optional actor, idempotency, ETag helpers on mutations)
createGroupSsoTRepository In-memory per-group snapshot, adoption, regression refusal, ensureFresh / verifyCurrent
createServicesRefreshHandler Auth + target match + invoke host refresh
deriveRefreshTarget / matchRefreshTarget HMAC addressing
groupSsotEtag / groupSsotIfNoneMatch ETag helpers
ServicesClientError / isServicesClientError Structured errors

Typical construction:

createServicesClient({ baseUrl, machineCredential })

createGroupSsoTRepository({ client, onAdopted? })

createServicesRefreshHandler({ notificationAuthSecret, notificationTargetKey, knownGroupIds, refreshGroup })

Platform X still MUST own: protected storage of machine credential, refresh secret, and target key; refresh HTTP route; locally known group ids for target matching; local projection beyond in-memory snapshot if the process must survive restart; actor authority for mutations; local authorization before mutations; browser payload sanitization; TLS with certificate verification; post-adoption application effects.

§11 Platform X implementation checklist

Engineering steps for a new Platform X. Acceptance condition is “done” before moving on.

  1. Establish the Platform X backend — process isolated from the browser bundle; HTTPS in production; backend starts without embedding Services credentials in frontend assets.
  2. Install the exact approved package version — dependencies["@simplexable/services-platform-client"] === "0.1.0" from registry, not file:; preflight package inspection passes.
  3. Keep actor authority on the Platform X backend — actor JWTs never enter the browser; fail closed when a valid actor is unavailable for actor-authorized operations; never return actorToken in bootstrap/session JSON to the browser.
  4. Integrate Services login / handoff — complete Services login, then Platform X backend calls POST /users/validate-handoff (current Services auth path, not /external/v1).
  5. Instantiate the Services client — all /external/v1 identity, SSoT, mutation, and connection calls through the package; login/handoff remains on Services auth routes in §2.2.
  6. Instantiate a per-group SSoT repository — createGroupSsoTRepository; call ensureFresh / verifyCurrent; refuse lower revision.
  7. Implement the local projection / access boundary — map ServicesGroup / ServicesUser into the platform roster/session model; fail closed when no snapshot exists.
  8. Implement the authenticated refresh endpoint — HTTPS POST route; createServicesRefreshHandler with notification secret, target key, known group ids, and refresh function that rereads SSoT.
  9. Integrate actor-backed mutations where required — machine + actor + idempotency + If-Match via package methods; local authorization first.
  10. Keep secrets out of frontend / bootstrap — allowlist bootstrap fields; never send machine credential, actor JWT, refresh secrets, target key, or DB password.
  11. Configure production TLS — valid certificates; remote TLS verification not disabled.
  12. Prepare deployment registration inputs — operator can run preflight without secrets on argv.
  13. Install credentials securely — migrate-platform-x.sh --install (or provisioner stdout → installer stdin); env 0600.
  14. Verify — --verify / verify-install.mjs; package 0.1.0, SSoT loaded, connection fields present without printing password.
  15. Perform controlled acceptance — prove the human path once per new platform type (§16); reversible visible mutation recommended for brand-new platform type, not every later deploy.

§12–§16 Installation and verification

  • Preflight (--check) — non-mutating; validates inputs, package version, permissions.
  • Install (--install) — mutating; creates deployment records, machine credential, notification secret, target key; writes protected env.
  • Verify (--verify) — mandatory on every install; machine path against live deployment.

Automated verification is mandatory on every install. Behavioral acceptance (login, roster, optional visible mutation) is mandatory for a new platform type, not required to re-prove on routine deploys.

§19 Security invariants

  1. No machine credential in the browser.
  2. No actor JWT in the browser.
  3. No DB password in the browser or in logs.
  4. No secret-bearing argv.
  5. Services persists only the machine-secret digest.
  6. Target HMAC is addressing, not authentication.
  7. Machine auth, actor auth, and refresh auth are three distinct secrets.
  8. Production transport is HTTPS; TLS verification not disabled for remote hosts.
  9. Credential authenticates only the bound deployment/group.
  10. Stale or legacy actor tokens are rejected.
  11. SSoT revision regression is rejected.
  12. Mutation authority remains Services-owned; Platform X sends intent only.
  13. Refresh body is exactly { target }; no identity payload.
  14. Protected env is 0600.
  15. Exact package version 0.1.0 until deliberately adopted.

§20 What Platform X does NOT need to implement

  • Services password policy or user/email normalization
  • SSoT revision policy or “is this change revision-worthy?”
  • Actor-token validation semantics (signature, audience, authority versions)
  • Target HMAC as if it were a capability
  • Duplicate mutation/idempotency stores for Services-owned operations
  • A browser-to-Services identity client
  • Legacy /users/lookup-group, /users/group-ssot-freshness, or /users/group-ssot-projection as the identity path
  • API_ACCESS_TOKEN / user_groups.api_token as external-v1 machine auth
  • Co-authoritative or hybrid user/group ownership

Public extraction from the canonical Platform X implementation specification (Services reference release v2026.09.24.03). Omitted: deployment identifiers, operator hostnames, reference-consumer acceptance narratives, historical compatibility paths, and internal script paths. Package: @simplexable/services-platform-client.