Data model
The tables behind Portline and who can read and write each one.
All tables live in the public schema with a pl_ prefix, and every row carries a workspace_id. Row-level security goes through two helpers: pl.role_in(workspace) returns your role, and pl.can(workspace, area, level) answers "may this user do this here", checking membership, plan features and subscription status.
"View", "edit" and "approve" below mean the level in that table's area. "+ fleet" means the plan must include that feature too.
Workspace and people
| Table | Holds | Read | Write |
|---|---|---|---|
pl_workspaces | Name, slug, timezone | Members | Owner (name and timezone only) |
pl_subscriptions | Plan, status, seats, period end | Members | Service role only |
pl_members | Role, display name, title, email | Members | Owner and admin, guarded by a trigger |
pl_notifications | Title, body, link, read time | Your own | read_at only |
pl_audit | Who did what, when | Approve | Insert as yourself only; never updated |
Shipments and containers
| Table | Holds | Read | Write |
|---|---|---|---|
pl_customers | Customer name and country | View | Edit |
pl_ports | UN/LOCODE, name, country, position | Everyone signed in | Service role |
pl_shipments | Code, customer, route, mode, status, cargo, weight, container, driver, incoterm, ETD/ETA | View | Edit |
pl_shipment_stops | Route checkpoints in order, planned and actual times | View | Edit |
pl_shipment_events | The "latest updates" timeline | View | Edit |
pl_documents | Bill of lading, customs declaration, invoices, with review status | View | Edit to upload; approve to review |
pl_containers | ISO 6346 number, type, reefer set point, status, position | View | Edit |
pl_telemetry | Reefer temperature readings | View + telemetry | Service role (sensor feed) |
Fleet, warehouses and docks
| Table | Holds | Read | Write |
|---|---|---|---|
pl_assets | Trucks, vessels, drones with status and position | View + fleet | Edit |
pl_drivers | Name, phone, carrier, truck, trailer, plate | View + fleet | Edit |
pl_warehouses | Site, city, capacity and used m² | View + warehouses | Edit |
pl_zones | Zones per site with utilisation | View + warehouses | Edit |
pl_stock | SKU, product, location, on hand, reorder point, ETA | View + warehouses | Edit |
pl_dock_doors | Doors per warehouse and their type | View + docks | Approve |
pl_dock_appointments | Truck, carrier, direction, times, status, check-in and check-out | View + docks | Edit; check-out needs check-in |
Messages
| Table | Holds | Read | Write |
|---|---|---|---|
pl_threads | Subject, linked shipment or driver | View | Edit |
pl_messages | Author, body, time | View | Edit, authored as yourself |
pl_thread_reads | Where each member last read a thread | Your own | Your own |
Plan features
pl.plan_features mirrors the plan catalogue in @portline/pricing, so the database and the app agree on which plan includes which feature.
Demo ids
The demo generator creates UUID-shaped ids from stable keys. The local seed uses the same generator, so a shipment has the same id and code in demo mode and in local mode.