Skip to main content

Tables

Types below are the PostgreSQL types. Nullability is the application requirement. UUID primary keys and created_at are present on every table. updated_at is present on rows that change. Append-only tables omit updated_at.

Amounts are cents. currency is char(3) and must be USD.

Identity​

users​

Customer and administrator accounts.

ColumnTypeRequiredNotes
iduuidyesPrimary key.
full_nametextyesDisplay name.
emailtextyesUnique, lowercase, trimmed.
phonetextnoContact number.
roleenumyesCUSTOMER or ADMIN.
statusenumyesPENDING_SETUP, ACTIVE, SUSPENDED, DISABLED.
created_at, updated_attimestamptzyesUTC.

user_credentials​

ColumnTypeRequiredNotes
user_iduuidyesPrimary key and foreign key to users.
password_hashtextyesArgon2id hash.
password_changed_attimestamptzyesRotated on reset and change.

refresh_tokens​

The access token is a signed JWT and is not stored. This table stores only refresh tokens.

ColumnTypeRequiredNotes
iduuidyesPrimary key.
user_iduuidyesForeign key.
token_hashtextyesUnique SHA-256 of the refresh token.
expires_attimestamptzyesInitial lifetime is 14 days.
revoked_attimestamptznoSet on logout, rotation, or password reset.

account_setup_tokens​

One-time account activation after a verified first payment.

ColumnTypeRequiredNotes
iduuidyesPrimary key.
user_iduuidyesForeign key.
token_hashtextyesUnique hash. The raw token is emailed once.
expires_attimestamptzyesInitial lifetime is 72 hours.
used_attimestamptznoNull until consumed. One unused row per user.

password_reset_tokens​

Same shape as account setup tokens. Initial lifetime is 1 hour. Supporting table for password recovery.

user_mfa_factors​

ColumnTypeRequiredNotes
iduuidyesPrimary key.
user_iduuidyesForeign key.
factor_typetextyestotp for this edition.
secret_ciphertexttextyesEncrypted shared secret. Never the plaintext secret.
enabled_attimestamptznoNull until the administrator confirms a code.

Catalog and bookings​

services​

ColumnTypeRequiredNotes
iduuidyesPrimary key.
nametextyesCatalog name.
descriptiontextnoPublic description.
activebooleanyesInactive services are hidden.

service_packages​

ColumnTypeRequiredNotes
iduuidyesPrimary key.
service_iduuidyesForeign key.
nametextyesPackage name.
price_centsintegeryesUSD cents, zero or greater.
currencychar(3)yesUSD.
duration_minutesintegeryesGreater than zero.
activebooleanyesInactive packages cannot be booked.

bookings​

ColumnTypeRequiredNotes
iduuidyesPrimary key.
customer_iduuidyesForeign key to users. Indexed.
package_iduuidyesForeign key to service_packages.
scheduled_attimestamptzyesIndexed.
locationtextyesSession location supplied by the customer.
statusenumyesSee the booking status model.
approved_byuuidnoAdministrator who confirmed the booking.
approved_attimestamptznoRequired when status is CONFIRMED.
decision_notetextnoReason recorded with a rejection or cancellation.

orders​

One order per booking.

ColumnTypeRequiredNotes
iduuidyesPrimary key.
customer_iduuidyesIndexed.
booking_iduuidyesUnique foreign key.
order_numbertextyesUnique human-readable number.
subtotal_centsintegeryesService subtotal before the reward discount.
discount_centsintegeryesReward discount. Zero when none is applied.
total_centsintegeryessubtotal_cents - discount_cents.
currencychar(3)yesUSD.
statusenumyesIndexed. Pending, paid, failed, refund states, or cancelled.

order_items​

ColumnTypeRequiredNotes
iduuidyesPrimary key.
order_iduuidyesForeign key.
package_iduuidyesPackage at time of purchase.
quantityintegeryesGreater than zero. This edition uses 1.
unit_price_centsintegeryesSnapshot of the package price.
currencychar(3)yesUSD.
descriptiontextyesSnapshot of the package name.

Payments​

payments​

ColumnTypeRequiredNotes
iduuidyesPrimary key.
order_iduuidyesForeign key. Indexed.
providerenumyesSTRIPE.
provider_payment_idtextnoUnique with provider when present.
amount_centsintegeryesUSD cents.
currencychar(3)yesUSD.
statusenumyesIndexed. Pending, succeeded, failed, or refund states.

payment_webhook_events​

Deduplication table. A row is inserted in the same transaction that applies the event.

ColumnTypeRequiredNotes
iduuidyesPrimary key.
providerenumyesSTRIPE.
event_idtextyesUnique together with provider.
payload_hashtextyesHash of the verified payload.
processed_attimestamptznoSet when the transaction commits the effect.
received_attimestamptzyesArrival time.

There is no foreign key to payments. The event can be the first time the API learns the provider payment id.

idempotency_keys​

Supporting table for safe retries of booking and checkout posts.

ColumnTypeRequiredNotes
iduuidyesPrimary key.
user_iduuidnoNull for a first checkout before login.
scopetextyesOperation name, such as booking.create.
keytextyesClient Idempotency-Key. Unique with scope.
request_hashtextyesDetects reuse of a key with a different body.
response_codeintegeryesStored response status.
response_bodyjsonbyesStored response.
expires_attimestamptzyesKeys expire after 24 hours.

Galleries​

galleries​

ColumnTypeRequiredNotes
iduuidyesPrimary key.
customer_iduuidyesIndexed.
booking_iduuidyesUnique. One gallery for one booking.
titletextyesGallery title.
publication_statusenumyesDRAFT, PUBLISHED, ARCHIVED.
access_statusenumyesIndexed. PENDING_APPROVAL, APPROVED, REVOKED.
approved_byuuidnoRequired while access is APPROVED.
approved_attimestamptznoRequired while access is APPROVED.

The current access status stays on this table so authorization is a single-row check. History is the next table.

ColumnTypeRequiredNotes
iduuidyesPrimary key.
gallery_iduuidyesForeign key. Indexed with created_at.
reviewed_byuuidyesAdministrator.
decisionenumyesAPPROVED, REJECTED, or REVOKED.
reasontextnoOptional note.
created_attimestamptzyesAppend-only.

photos​

ColumnTypeRequiredNotes
iduuidyesPrimary key.
gallery_iduuidyesForeign key.
storage_keytextyesPrivate object key for the original.
thumbnail_keytextnoSet when the worker finishes the thumbnail.
statusenumyesPENDING_UPLOAD, PROCESSING, READY, FAILED, REMOVED.
content_typetextnoDetected type after signature check.
byte_sizeintegernoSize of the original.

photo_ratings​

ColumnTypeRequiredNotes
iduuidyesPrimary key.
photo_iduuidyesUnique together with customer_id.
customer_iduuidyesMust be the gallery owner.
ratingintegeryes1 through 5.
feedbacktextnoOptional comment.

Referrals​

referral_codes​

ColumnTypeRequiredNotes
iduuidyesPrimary key.
user_iduuidyesUnique. One code per customer.
codetextyesUnique public code.
activebooleanyesInactive codes cannot be attributed.

referrals​

ColumnTypeRequiredNotes
iduuidyesPrimary key.
referrer_iduuidyesIndexed. Must differ from referred_user_id.
referred_user_iduuidyesUnique. One attribution per customer.
qualifying_order_iduuidnoUnique once the first paid order qualifies.
statusenumyesATTRIBUTED, QUALIFIED, REWARDED, REJECTED, REVERSED.

reward_policies​

ColumnTypeRequiredNotes
iduuidyesPrimary key.
percentage_basis_pointsintegeryes0 through 10,000.
reward_validity_daysintegernoNull means credits do not expire.
activebooleanyesOnly one row may be active.
valid_fromtimestamptzyesInclusive start.
valid_untiltimestamptznoExclusive end when set.

referral_rewards​

ColumnTypeRequiredNotes
iduuidyesPrimary key.
referral_iduuidyesUnique together with qualifying_order_id.
qualifying_order_iduuidyesUnique. One reward per order.
policy_iduuidyesPolicy used for the calculation.
eligible_subtotal_centsintegeryesSnapshot of the eligible USD base.
basis_points_appliedintegeryesSnapshot of the rate.
amount_centsintegeryesCalculated reward.
currencychar(3)yesUSD.
statusenumyesPENDING, AVAILABLE, REDEEMED, REVERSED, EXPIRED.
expires_attimestamptznoSet from the policy when the reward is created.

reward_ledger​

Immutable credits, redemptions, reversals, and expirations. Balance is the sum of amount_cents.

ColumnTypeRequiredNotes
iduuidyesPrimary key.
user_iduuidyesThe referrer who holds the balance. Indexed with created_at.
reward_iduuidnoSet for credits, reversals, and expirations of a reward.
redemption_iduuidnoSet when the entry reserves or releases a redemption.
entry_typeenumyesCREDIT, REDEMPTION, REVERSAL, EXPIRATION.
amount_centsintegeryesSigned. Credits are positive. Redemptions and expirations are negative.
currencychar(3)yesUSD.

reward_redemptions​

ColumnTypeRequiredNotes
iduuidyesPrimary key.
user_iduuidyesReferrer spending the balance.
order_iduuidyesFuture order receiving the discount.
amount_centsintegeryesPositive discount amount.
currencychar(3)yesUSD.
statusenumyesRESERVED, APPLIED, RELEASED, REVERSED.

The ledger entry that reserves the discount is written in the same transaction as the redemption row. APPLIED does not write a second debit.

Operations​

notifications​

ColumnTypeRequiredNotes
iduuidyesPrimary key.
user_iduuidyesRecipient. Indexed with read_at.
typetextyesFor example booking.payment_received or gallery.access_approved.
payloadjsonbyesStructured context. No secrets and no raw tokens.
read_attimestamptznoNull until read.

notification_deliveries​

ColumnTypeRequiredNotes
iduuidyesPrimary key.
notification_iduuidyesForeign key.
channelenumyesEMAIL or IN_APP.
statusenumyesPENDING, SENT, FAILED, CANCELLED.
attempt_countintegeryesStarts at 0.
last_attempt_attimestamptznoLast delivery attempt.

background_jobs​

ColumnTypeRequiredNotes
iduuidyesPrimary key.
job_typetextyesSee the component job list.
payloadjsonbyesIds the worker needs.
statusenumyesIndexed with available_at.
available_attimestamptzyesClaim when this time has passed.
attempt_countintegeryesRetry count.
last_errortextnoLast failure message, without secrets.
locked_attimestamptznoSet while a worker owns the job.

audit_logs​

ColumnTypeRequiredNotes
iduuidyesPrimary key.
actor_user_iduuidnoNull for a verified webhook.
actiontextyesFor example booking.approve or gallery.access.revoke.
resource_typetextyesTable or aggregate name.
resource_iduuidyesTarget row.
metadatajsonbnoBefore and after status. No passwords, tokens, or card data.
created_attimestamptzyesAppend-only. Indexed.