Skip to content

User Account Service (UAS)

UAS — User Account Service

Identity: users, emails, passcodes, and payment methods. Public stat lives on API Gateway; all other operations are direct Lambda (CLI wraps them).

Surface map (contract-only)

  • Public API (API Gateway): POST https://api.g3nretailstack.com/uas/stat → user snapshot (requires email+passcode; no user_id-only mode). Optional cccode may be provided in body or x-cccode header and is validated/canonicalized; mismatch → 400.
  • Direct Lambda actions: userCreate, userSnapshot (userGet), userStatusSet, userConfigSet, email (emailAdd/list/setPrimary/issueToken/confirmToken/doom), passcode (passcodeSet/reset), payment methods (pmCreate/list/setStatus/promote/demote/doom/vacateToken).
  • CLI: cli/bin/g3n.js (g3n uas ...), requires --profile; optional --region; JSON output by default. Calls the same Lambdas.
  • Pagination: list calls (emailList, pmList) default to limit 8, clamp 1–256, return opaque next_token.
  • Email canonicalization: email inputs are trimmed + lowercased; duplicates are case-insensitive and stored emails are canonical.
  • MCP: unauthenticated protocol doc at https://mcp.g3nretailstack.com/uas/PROTOCOL.md (mirrored to /uas/PROTOCOL.md here).
  • OpenAPI: https://doc.g3nretailstack.com/uas/openapi.yaml
  • Optimistic concurrency (revision): any state-changing action on an existing user requires expected_revision (use revision returned by stat/userGet). Missing → 428 expected-revision-required; mismatch → 409 conflict with error.details.{provided_revision,current_revision,current_record}.

Responses share { success, data?, error?, build, stats? } with build_id + UTC timestamp shown in every footer. Stats include call, service, request_id, timestamp_utc, latency_ms, and passthrough context when provided (direct Lambdas forward orgcode/cccode verbatim; /stat validates cccode).

Record lifecycles and operations

User + status FSM (unverified → verified ↔ suspended → doomed)

  • Create (userCreate): issue a user with email + passcode; returns user_id and account_ref. Use to onboard new identities. Errors: duplicate-email, validation-error.
  • Snapshot (userSnapshot/userGet): fetch current user/emails/payment methods; optionally include payment history.
  • Status (userStatusSet): { user_id, status, expected_revision, reason?, actor? }. Allowed transitions: unverified→verified, unverified→doomed, verified↔suspended, suspended→doomed, verified→doomed. Verified requires verified primary email + passcode set. Errors: invalid-transition, not-found.
  • Session cap (userConfigSet): { user_id, max_active_sessions: number|null, expected_revision, reason?, actor? } (32–8192 when set; null clears). Errors: validation-error for out-of-range values.
  • Use case: create → verify email → set verified → set per-user session cap if needed → consume via USM for sessions.

Example (direct Lambda payload):

json
{ "email": "user@example.com", "passcode": "Abcd!234", "caption": "Retail staff iPad", "actor": "ops-user" }

Response: { "success": true, "data": { "user_id": "u123", "account_ref": "..." }, "build": {...}, "stats": {...} }

Emails (unverified ↔ verified → doomed; primary required)

  • Add/list (emailAdd/emailList): emailAdd requires { expected_revision }; list is paginated. Duplicate emails across users are rejected.
  • Verify (emailIssueTokenemailConfirmToken): both require { expected_revision }. Issue verification token (last token wins, 48h validity). Confirm marks email verified; if primary is verified, user can be verified. Errors: invalid-token, token-expired, duplicate-email, validation-error.
  • Primary (emailSetPrimary): requires { expected_revision }. One primary email per user; primary cannot be doomed. If primary becomes unverified, user status cannot be verified.
  • Doom (emailDoom): requires { expected_revision }. Terminal; doomed emails cannot be primary. Errors: invalid-transition, not-found.
  • Use case: add secondary email → set primary → issue/confirm token → rotate primary as needed (re-verify new primary).

Example (confirm token):

json
{ "user_id": "u123", "token": "base64token", "expected_revision": "rev-123", "actor": "ops-user", "reason": "email-verify" }

Response: { "success": true, "data": { "email": "user@example.com", "status": "verified" }, "build": {...}, "stats": {...} }

Passcodes (set/reset)

  • Set/reset (passcodeSet/passcodeReset): { user_id, passcode, expected_revision, reason?, actor? }. Enforces policy (length ≥8 with upper/lower/number/special) and reuse guard. Errors: passcode-policy-failed, passcode-reuse, validation-error.
  • Use case: set during onboarding; rotate on compromise; reset after verification.

Payment methods (pending → active ↔ suspended → doomed)

  • Create/list (pmCreate/pmList): pmCreate requires { expected_revision }; uniqueness on processor+token_type+token; list is paginated and ordered (active, pending, suspended, doomed). Errors: payment-uniqueness-conflict, validation-error.
  • Status (pmSetStatus, pmPromote, pmDemote, pmDoom): require { expected_revision }. Manage lifecycle. Doomed removes token and is terminal.
  • Default ordering: first active; else first pending; else first suspended; never doomed.
  • Vacate token (pmVacateToken): requires { expected_revision }. Nulls stored token for a doomed/retired PM. Errors: not-found, invalid-transition.
  • Use case: add PM → promote to active → demote/suspend as needed → doom or vacate when revoked.

Example (promote):

json
{ "user_id": "u123", "pm_id": "pm_abc", "expected_revision": "rev-123", "reason": "set-default", "actor": "ops-user" }

Response: { "success": true, "data": { "pm_id": "pm_abc", "status": "active" }, "build": {...}, "stats": {...} }

Error tags (representative)

  • duplicate-email, invalid-token, token-expired, invalid-transition, passcode-policy-failed, passcode-reuse, payment-uniqueness-conflict, not-found, validation-error, unauthorized, internal-error.

See Surfaces for per-operation request/response examples, accepted/rejected transitions, and CLI usage. For protocol-level detail, consult the MCP doc.