Files

59 lines
2.1 KiB
TypeScript

export type InvitationDisplayState = "active" | "expired" | "revoked";
export function deriveInvitationDisplayState(
invitation: { state: string; ends_at: string | null; revoked_at: string | null },
now = new Date().toISOString(),
): InvitationDisplayState {
if (invitation.state === "revoked" || invitation.revoked_at) return "revoked";
if (invitation.ends_at && invitation.ends_at <= now) return "expired";
return "active";
}
/**
* Create the replay record only while the requested administrator invitation
* is still revocable. D1 batch serialization makes this predicate the fence
* for concurrent revocations with different idempotency keys.
*
* Parameters: scope, key, request hash, response JSON, expiry, now, grant id.
*/
export const CREATE_INVITATION_REVOCATION_IDEMPOTENCY_SQL = `
INSERT INTO idempotency_records
(scope, key, request_hash, response_json, status_code, expires_at, created_at)
SELECT ?1, ?2, ?3, ?4, 200, ?5, ?6
FROM entitlement_grants
WHERE id = ?7 AND source = 'admin_exemption'
AND state = 'active' AND revoked_at IS NULL
`;
/** Parameters: revoked time, grant id, scope, key, request hash. */
export const REVOKE_INVITATION_SQL = `
UPDATE entitlement_grants
SET state = 'revoked', revoked_at = ?1
WHERE id = ?2 AND source = 'admin_exemption'
AND state = 'active' AND revoked_at IS NULL
AND EXISTS (
SELECT 1 FROM idempotency_records
WHERE scope = ?3 AND key = ?4 AND request_hash = ?5
)
`;
/**
* Append exactly one audit row for a successful revocation. The audit id is
* deterministic per idempotency key, so a replay cannot duplicate history.
*/
export const AUDIT_INVITATION_REVOCATION_SQL = `
INSERT OR IGNORE INTO audit_events
(id, actor_id, action, target_type, target_id, reason,
before_json, after_json, correlation_id, created_at)
SELECT ?1, ?2, 'entitlement.invitation_revoked', 'entitlement_grant', ?3,
?4, ?5, ?6, ?7, ?8
WHERE EXISTS (
SELECT 1 FROM idempotency_records
WHERE scope = ?9 AND key = ?10 AND request_hash = ?11
)
AND EXISTS (
SELECT 1 FROM entitlement_grants
WHERE id = ?3 AND state = 'revoked' AND revoked_at = ?8
)
`;