Documentation
¶
Overview ¶
Package customer is the CUSTOMER management surface (/v1/admin/customers*) — the operator cockpit's core: the live fleet customer list (incl. new self-serve signups), one-customer detail, and the audited management ACTIONS (grant credit, suspend, reactivate).
It aggregates the SAME real upstreams the rest of admin reads — IAM for the org directory + user/owner/status, commerce for balance/spend/plan/ledger — and adds the two write levers an operator needs:
- GRANT CREDIT is a real commerce Deposit landing in the org's own wallet, via the ONE core credit-write path (core.ApplyGrant).
- SUSPEND / REACTIVATE flips IAM `isForbidden` on the org's users — IAM refuses a forbidden user at login AND at token issuance, so a suspended customer cannot sign in or mint a fresh token. Fully reversible.
SECURITY. Every route is mounted behind core.Guard (SuperAdmin only, fail-closed). The write actions REPLAY THE CALLER'S OWN SuperAdmin credential to IAM, and each is recorded to cloud's tamper-evident audit trail with a redacted BEFORE/AFTER.
Index ¶
- func CustomerDetail(s *cloud.Service[core.State], c *zip.Ctx) error
- func Customers(s *cloud.Service[core.State], c *zip.Ctx) error
- func GrantCredit(s *cloud.Service[core.State], c *zip.Ctx) error
- func Grants(s *cloud.Service[core.State], c *zip.Ctx) error
- func IssueGrant(s *cloud.Service[core.State], c *zip.Ctx) error
- func ReactivateCustomer(s *cloud.Service[core.State], c *zip.Ctx) error
- func Routes(app cloud.Router, s *cloud.Service[core.State])
- func SuspendCustomer(s *cloud.Service[core.State], c *zip.Ctx) error
- type CustomerDetailData
- type CustomerRow
- type CustomerTxn
- type CustomerUser
- type GrantRow
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func CustomerDetail ¶
CustomerDetail answers GET /v1/admin/customers/:org.
func GrantCredit ¶
GrantCredit answers POST /v1/admin/customers/:org/credit — a staff credit grant to the path org, funneled through the ONE core credit-write path (core.ApplyGrant).
func Grants ¶
Grants answers GET /v1/admin/grants — the credit-grant ledger across ALL orgs, newest first, projected from the audit trail. Filters: ?org, ?result (success|error), ?limit. Honest empty when no local audit store is configured.
func IssueGrant ¶
IssueGrant answers POST /v1/admin/grants — issue a credit grant to any org from the operator Grants view (org in the body). It funnels through the SAME core.ApplyGrant POST /v1/admin/customers/:org/credit uses, so there is exactly ONE credit-write path.
func ReactivateCustomer ¶
ReactivateCustomer restores access for every member of the org.
Types ¶
type CustomerDetailData ¶
type CustomerDetailData struct {
Org string `json:"org"`
Display string `json:"display"`
OwnerEmail string `json:"ownerEmail"`
Plan string `json:"plan"`
Status string `json:"status"`
Created string `json:"created"`
BalanceCents int64 `json:"balanceCents"`
SpendCents int64 `json:"spendCents"`
MRRCents int64 `json:"mrrCents"`
APIKeys int `json:"apiKeys"`
Users []CustomerUser `json:"users"`
Transactions []CustomerTxn `json:"transactions"`
}
CustomerDetailData is the GET /v1/admin/customers/:org payload.
type CustomerRow ¶
type CustomerRow struct {
Org string `json:"org"`
Display string `json:"display"`
OwnerEmail string `json:"ownerEmail"`
Plan string `json:"plan"`
Status string `json:"status"` // "active" | "suspended"
Users int `json:"users"`
BalanceCents int64 `json:"balanceCents"`
SpendCents int64 `json:"spendCents"`
MRRCents int64 `json:"mrrCents"`
Created string `json:"created"`
LastActive string `json:"lastActive"`
}
CustomerRow is one row in GET /v1/admin/customers — a fleet customer at a glance.
type CustomerTxn ¶
type CustomerTxn struct {
ID string `json:"id"`
Type string `json:"type"` // "deposit" (credit) | "withdraw" (usage)
Cents int64 `json:"cents"`
Currency string `json:"currency"`
Notes string `json:"notes,omitempty"`
Time string `json:"time"`
}
CustomerTxn is one ledger row in the detail's top-up/usage history.
type CustomerUser ¶
type CustomerUser struct {
Name string `json:"name"`
Email string `json:"email"`
IsAdmin bool `json:"isAdmin"`
Forbidden bool `json:"forbidden"`
HasAPIKey bool `json:"hasApiKey"`
LastSignin string `json:"lastSignin"`
Created string `json:"created"`
}
CustomerUser is one member in the customer detail (no secrets — the AccessKey PRESENCE is surfaced as hasApiKey, never the key itself).
type GrantRow ¶
type GrantRow struct {
Org string `json:"org"`
AmountCents int64 `json:"amountCents"`
Currency string `json:"currency"`
Source string `json:"source"` // "trial" | "prepaid"
Reason string `json:"reason,omitempty"`
Actor string `json:"actor"` // staff email (or sub) who issued it
CreatedAt string `json:"createdAt"`
TransactionID string `json:"transactionId,omitempty"`
Result string `json:"result"` // success | error
}
GrantRow is one row in GET /v1/admin/grants.