Team seats
The paying customer and the workspace receiving capacity can be different subjects. Your application still owns workspace membership, invitations, and RBAC.
import { Access, Billing, Offer, Purchase, Seats, assignSeat, checkSeatAssignmentAccess, createCheckout, processPaymentNotification, registerOffers, unassignSeat,} from "@byfungsi/sapa";
const teamAccess = yield * Access.entitlements({ entitlements: ["workspace.use"], duration: "purchased_period", });const teamCapacity = yield * Seats.capacity({ pool: "workspace.members", quantity: "purchase_quantity", entitlement: "workspace.use", });const teamPurchase = yield * Purchase.parse({ key: "workspace.team.access", revision: 1, provides: [teamAccess, teamCapacity], });const teamBilling = yield * Billing.perSeatSubscription({ family: "workspace", interval: "month", price: { currency: "IDR", amount: 75_000n }, minimumQuantity: 1, maximumQuantity: 100, });const team = yield * Offer.parse({ key: "workspace.team", revision: 1, purchase: teamPurchase, billing: teamBilling, });
yield * registerOffers([team]);yield * createCheckout({ type: "offer", offerKey: team.key, offerRevision: team.revision, quantity: 10, beneficiary: { type: "merchant_subject", subjectId: "workspace-42" }, provider: "midtrans", customer: { externalId: "billing-customer-42", email: "owner@example.com", name: "Workspace Owner", }, successUrl, cancelUrl, clientIp: null, idempotencyKey: "workspace-42-seats-10", });yield * processPaymentNotification({ provider: "midtrans", payload: rawProviderPayload, });
const assignment = yield * assignSeat({ idempotencyKey: "workspace-42-member-7", beneficiary: { type: "merchant_subject", subjectId: "workspace-42" }, pool: "workspace.members", memberId: "member-7", principal: "workspace-admin-3", });const access = yield * checkSeatAssignmentAccess({ beneficiary: { type: "merchant_subject", subjectId: "workspace-42" }, pool: "workspace.members", memberId: "member-7", entitlement: "workspace.use", });
yield * unassignSeat({ idempotencyKey: "workspace-42-member-7-remove", assignmentId: assignment.assignmentId, principal: "workspace-admin-3", });Authenticate and authorize the principal in your host before calling SAPA.
Assignments are capacity accounting, not identity proof. To reduce quantity,
first unassign enough members, then schedule a guarded next-period quantity
change and settle the renewal. SAPA rejects a reduction below active occupancy.