e579fe5b6e
Occupancy is a fold over the signed ledger (entries minus exits per identity);
getOccupancy returns {count, capacity, free, full}. Capacity is a single-row
site_config table (admin-set; null = uncapped; migration 0001, additive).
FULL gate lives in the transient entry flow: when full, refuse (no ticket, no
vehicle_entry, no open) and sign an anomaly. Permit entry is NOT gated --
subscribers are admitted past transient-full (their own maxConcurrent still
applies), so occupancy can read over capacity by design (reserve-for-permits).
Routes: GET /api/occupancy + GET /api/site-config (any role), PUT
/api/site-config (admin; non-negative int or null). Web SiteSettings: live
occupancy + FULL badge (everyone), capacity editor (admin).
Verified: fill to cap -> 3rd transient refused; permit admitted past full; exit
frees a slot; RBAC (operator can't set, -5 -> 400); verifyChain ok. Physical
FULL-sign relay output deferred.
724 lines
18 KiB
JSON
724 lines
18 KiB
JSON
{
|
|
"version": "6",
|
|
"dialect": "sqlite",
|
|
"id": "538cd745-2fe9-410b-bb9f-e4d3c2086211",
|
|
"prevId": "cd09c11f-4306-4ac8-a335-7c050d080ab6",
|
|
"tables": {
|
|
"blocklist": {
|
|
"name": "blocklist",
|
|
"columns": {
|
|
"id": {
|
|
"name": "id",
|
|
"type": "text",
|
|
"primaryKey": true,
|
|
"notNull": true,
|
|
"autoincrement": false
|
|
},
|
|
"kind": {
|
|
"name": "kind",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": true,
|
|
"autoincrement": false
|
|
},
|
|
"value": {
|
|
"name": "value",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": true,
|
|
"autoincrement": false
|
|
},
|
|
"reason": {
|
|
"name": "reason",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": false,
|
|
"autoincrement": false
|
|
},
|
|
"active": {
|
|
"name": "active",
|
|
"type": "integer",
|
|
"primaryKey": false,
|
|
"notNull": true,
|
|
"autoincrement": false,
|
|
"default": true
|
|
},
|
|
"added_by": {
|
|
"name": "added_by",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": false,
|
|
"autoincrement": false
|
|
},
|
|
"added_at": {
|
|
"name": "added_at",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": true,
|
|
"autoincrement": false,
|
|
"default": "(current_timestamp)"
|
|
}
|
|
},
|
|
"indexes": {},
|
|
"foreignKeys": {},
|
|
"compositePrimaryKeys": {},
|
|
"uniqueConstraints": {},
|
|
"checkConstraints": {}
|
|
},
|
|
"device_events": {
|
|
"name": "device_events",
|
|
"columns": {
|
|
"id": {
|
|
"name": "id",
|
|
"type": "text",
|
|
"primaryKey": true,
|
|
"notNull": true,
|
|
"autoincrement": false
|
|
},
|
|
"device_id": {
|
|
"name": "device_id",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": false,
|
|
"autoincrement": false
|
|
},
|
|
"lane": {
|
|
"name": "lane",
|
|
"type": "integer",
|
|
"primaryKey": false,
|
|
"notNull": false,
|
|
"autoincrement": false
|
|
},
|
|
"category": {
|
|
"name": "category",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": false,
|
|
"autoincrement": false
|
|
},
|
|
"kind": {
|
|
"name": "kind",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": true,
|
|
"autoincrement": false
|
|
},
|
|
"detail": {
|
|
"name": "detail",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": false,
|
|
"autoincrement": false
|
|
},
|
|
"occurred_at": {
|
|
"name": "occurred_at",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": true,
|
|
"autoincrement": false,
|
|
"default": "(current_timestamp)"
|
|
}
|
|
},
|
|
"indexes": {},
|
|
"foreignKeys": {},
|
|
"compositePrimaryKeys": {},
|
|
"uniqueConstraints": {},
|
|
"checkConstraints": {}
|
|
},
|
|
"lane_devices": {
|
|
"name": "lane_devices",
|
|
"columns": {
|
|
"id": {
|
|
"name": "id",
|
|
"type": "text",
|
|
"primaryKey": true,
|
|
"notNull": true,
|
|
"autoincrement": false
|
|
},
|
|
"lane": {
|
|
"name": "lane",
|
|
"type": "integer",
|
|
"primaryKey": false,
|
|
"notNull": true,
|
|
"autoincrement": false
|
|
},
|
|
"category": {
|
|
"name": "category",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": true,
|
|
"autoincrement": false
|
|
},
|
|
"driver_id": {
|
|
"name": "driver_id",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": true,
|
|
"autoincrement": false
|
|
},
|
|
"config": {
|
|
"name": "config",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": true,
|
|
"autoincrement": false
|
|
},
|
|
"enabled": {
|
|
"name": "enabled",
|
|
"type": "integer",
|
|
"primaryKey": false,
|
|
"notNull": true,
|
|
"autoincrement": false,
|
|
"default": true
|
|
},
|
|
"created_at": {
|
|
"name": "created_at",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": true,
|
|
"autoincrement": false,
|
|
"default": "(current_timestamp)"
|
|
}
|
|
},
|
|
"indexes": {},
|
|
"foreignKeys": {},
|
|
"compositePrimaryKeys": {},
|
|
"uniqueConstraints": {},
|
|
"checkConstraints": {}
|
|
},
|
|
"ledger_events": {
|
|
"name": "ledger_events",
|
|
"columns": {
|
|
"id": {
|
|
"name": "id",
|
|
"type": "text",
|
|
"primaryKey": true,
|
|
"notNull": true,
|
|
"autoincrement": false
|
|
},
|
|
"index": {
|
|
"name": "index",
|
|
"type": "integer",
|
|
"primaryKey": false,
|
|
"notNull": true,
|
|
"autoincrement": false
|
|
},
|
|
"type": {
|
|
"name": "type",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": true,
|
|
"autoincrement": false
|
|
},
|
|
"direction": {
|
|
"name": "direction",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": false,
|
|
"autoincrement": false
|
|
},
|
|
"lane": {
|
|
"name": "lane",
|
|
"type": "integer",
|
|
"primaryKey": false,
|
|
"notNull": true,
|
|
"autoincrement": false
|
|
},
|
|
"source": {
|
|
"name": "source",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": false,
|
|
"autoincrement": false
|
|
},
|
|
"identity": {
|
|
"name": "identity",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": false,
|
|
"autoincrement": false
|
|
},
|
|
"payload": {
|
|
"name": "payload",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": false,
|
|
"autoincrement": false
|
|
},
|
|
"occurred_at": {
|
|
"name": "occurred_at",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": true,
|
|
"autoincrement": false
|
|
},
|
|
"prev_hash": {
|
|
"name": "prev_hash",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": false,
|
|
"autoincrement": false
|
|
},
|
|
"signature": {
|
|
"name": "signature",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": true,
|
|
"autoincrement": false
|
|
},
|
|
"key_id": {
|
|
"name": "key_id",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": true,
|
|
"autoincrement": false
|
|
}
|
|
},
|
|
"indexes": {
|
|
"ledger_events_index_unique": {
|
|
"name": "ledger_events_index_unique",
|
|
"columns": [
|
|
"index"
|
|
],
|
|
"isUnique": true
|
|
}
|
|
},
|
|
"foreignKeys": {},
|
|
"compositePrimaryKeys": {},
|
|
"uniqueConstraints": {},
|
|
"checkConstraints": {}
|
|
},
|
|
"permit_credentials": {
|
|
"name": "permit_credentials",
|
|
"columns": {
|
|
"id": {
|
|
"name": "id",
|
|
"type": "text",
|
|
"primaryKey": true,
|
|
"notNull": true,
|
|
"autoincrement": false
|
|
},
|
|
"permit_id": {
|
|
"name": "permit_id",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": true,
|
|
"autoincrement": false
|
|
},
|
|
"kind": {
|
|
"name": "kind",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": true,
|
|
"autoincrement": false
|
|
},
|
|
"value": {
|
|
"name": "value",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": true,
|
|
"autoincrement": false
|
|
}
|
|
},
|
|
"indexes": {},
|
|
"foreignKeys": {},
|
|
"compositePrimaryKeys": {},
|
|
"uniqueConstraints": {},
|
|
"checkConstraints": {}
|
|
},
|
|
"permit_plates": {
|
|
"name": "permit_plates",
|
|
"columns": {
|
|
"id": {
|
|
"name": "id",
|
|
"type": "text",
|
|
"primaryKey": true,
|
|
"notNull": true,
|
|
"autoincrement": false
|
|
},
|
|
"permit_id": {
|
|
"name": "permit_id",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": true,
|
|
"autoincrement": false
|
|
},
|
|
"plate": {
|
|
"name": "plate",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": true,
|
|
"autoincrement": false
|
|
}
|
|
},
|
|
"indexes": {},
|
|
"foreignKeys": {},
|
|
"compositePrimaryKeys": {},
|
|
"uniqueConstraints": {},
|
|
"checkConstraints": {}
|
|
},
|
|
"permits": {
|
|
"name": "permits",
|
|
"columns": {
|
|
"id": {
|
|
"name": "id",
|
|
"type": "text",
|
|
"primaryKey": true,
|
|
"notNull": true,
|
|
"autoincrement": false
|
|
},
|
|
"holder_name": {
|
|
"name": "holder_name",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": false,
|
|
"autoincrement": false
|
|
},
|
|
"contact": {
|
|
"name": "contact",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": false,
|
|
"autoincrement": false
|
|
},
|
|
"max_concurrent": {
|
|
"name": "max_concurrent",
|
|
"type": "integer",
|
|
"primaryKey": false,
|
|
"notNull": false,
|
|
"autoincrement": false,
|
|
"default": 1
|
|
},
|
|
"valid_from": {
|
|
"name": "valid_from",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": false,
|
|
"autoincrement": false
|
|
},
|
|
"valid_to": {
|
|
"name": "valid_to",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": false,
|
|
"autoincrement": false
|
|
},
|
|
"status": {
|
|
"name": "status",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": true,
|
|
"autoincrement": false,
|
|
"default": "'active'"
|
|
},
|
|
"created_at": {
|
|
"name": "created_at",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": true,
|
|
"autoincrement": false,
|
|
"default": "(current_timestamp)"
|
|
}
|
|
},
|
|
"indexes": {},
|
|
"foreignKeys": {},
|
|
"compositePrimaryKeys": {},
|
|
"uniqueConstraints": {},
|
|
"checkConstraints": {}
|
|
},
|
|
"sessions": {
|
|
"name": "sessions",
|
|
"columns": {
|
|
"id": {
|
|
"name": "id",
|
|
"type": "text",
|
|
"primaryKey": true,
|
|
"notNull": true,
|
|
"autoincrement": false
|
|
},
|
|
"lane": {
|
|
"name": "lane",
|
|
"type": "integer",
|
|
"primaryKey": false,
|
|
"notNull": false,
|
|
"autoincrement": false
|
|
},
|
|
"identity": {
|
|
"name": "identity",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": false,
|
|
"autoincrement": false
|
|
},
|
|
"source": {
|
|
"name": "source",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": false,
|
|
"autoincrement": false
|
|
},
|
|
"permit_id": {
|
|
"name": "permit_id",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": false,
|
|
"autoincrement": false
|
|
},
|
|
"entered_at": {
|
|
"name": "entered_at",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": true,
|
|
"autoincrement": false
|
|
},
|
|
"exited_at": {
|
|
"name": "exited_at",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": false,
|
|
"autoincrement": false
|
|
},
|
|
"state": {
|
|
"name": "state",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": true,
|
|
"autoincrement": false,
|
|
"default": "'open'"
|
|
},
|
|
"last_event_index": {
|
|
"name": "last_event_index",
|
|
"type": "integer",
|
|
"primaryKey": false,
|
|
"notNull": false,
|
|
"autoincrement": false
|
|
}
|
|
},
|
|
"indexes": {},
|
|
"foreignKeys": {},
|
|
"compositePrimaryKeys": {},
|
|
"uniqueConstraints": {},
|
|
"checkConstraints": {}
|
|
},
|
|
"setup_state": {
|
|
"name": "setup_state",
|
|
"columns": {
|
|
"id": {
|
|
"name": "id",
|
|
"type": "integer",
|
|
"primaryKey": true,
|
|
"notNull": true,
|
|
"autoincrement": false
|
|
},
|
|
"completed_at": {
|
|
"name": "completed_at",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": false,
|
|
"autoincrement": false
|
|
}
|
|
},
|
|
"indexes": {},
|
|
"foreignKeys": {},
|
|
"compositePrimaryKeys": {},
|
|
"uniqueConstraints": {},
|
|
"checkConstraints": {}
|
|
},
|
|
"site_config": {
|
|
"name": "site_config",
|
|
"columns": {
|
|
"id": {
|
|
"name": "id",
|
|
"type": "integer",
|
|
"primaryKey": true,
|
|
"notNull": true,
|
|
"autoincrement": false
|
|
},
|
|
"capacity": {
|
|
"name": "capacity",
|
|
"type": "integer",
|
|
"primaryKey": false,
|
|
"notNull": false,
|
|
"autoincrement": false
|
|
},
|
|
"updated_at": {
|
|
"name": "updated_at",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": true,
|
|
"autoincrement": false,
|
|
"default": "(current_timestamp)"
|
|
}
|
|
},
|
|
"indexes": {},
|
|
"foreignKeys": {},
|
|
"compositePrimaryKeys": {},
|
|
"uniqueConstraints": {},
|
|
"checkConstraints": {}
|
|
},
|
|
"tariff_versions": {
|
|
"name": "tariff_versions",
|
|
"columns": {
|
|
"id": {
|
|
"name": "id",
|
|
"type": "text",
|
|
"primaryKey": true,
|
|
"notNull": true,
|
|
"autoincrement": false
|
|
},
|
|
"tariff_id": {
|
|
"name": "tariff_id",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": true,
|
|
"autoincrement": false
|
|
},
|
|
"effective_from": {
|
|
"name": "effective_from",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": true,
|
|
"autoincrement": false
|
|
},
|
|
"currency": {
|
|
"name": "currency",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": true,
|
|
"autoincrement": false
|
|
},
|
|
"structure": {
|
|
"name": "structure",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": true,
|
|
"autoincrement": false
|
|
},
|
|
"created_by": {
|
|
"name": "created_by",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": false,
|
|
"autoincrement": false
|
|
},
|
|
"created_at": {
|
|
"name": "created_at",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": true,
|
|
"autoincrement": false,
|
|
"default": "(current_timestamp)"
|
|
}
|
|
},
|
|
"indexes": {},
|
|
"foreignKeys": {},
|
|
"compositePrimaryKeys": {},
|
|
"uniqueConstraints": {},
|
|
"checkConstraints": {}
|
|
},
|
|
"tariffs": {
|
|
"name": "tariffs",
|
|
"columns": {
|
|
"id": {
|
|
"name": "id",
|
|
"type": "text",
|
|
"primaryKey": true,
|
|
"notNull": true,
|
|
"autoincrement": false
|
|
},
|
|
"scope": {
|
|
"name": "scope",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": true,
|
|
"autoincrement": false,
|
|
"default": "'site'"
|
|
},
|
|
"name": {
|
|
"name": "name",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": true,
|
|
"autoincrement": false
|
|
},
|
|
"created_at": {
|
|
"name": "created_at",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": true,
|
|
"autoincrement": false,
|
|
"default": "(current_timestamp)"
|
|
}
|
|
},
|
|
"indexes": {},
|
|
"foreignKeys": {},
|
|
"compositePrimaryKeys": {},
|
|
"uniqueConstraints": {},
|
|
"checkConstraints": {}
|
|
},
|
|
"users": {
|
|
"name": "users",
|
|
"columns": {
|
|
"id": {
|
|
"name": "id",
|
|
"type": "text",
|
|
"primaryKey": true,
|
|
"notNull": true,
|
|
"autoincrement": false
|
|
},
|
|
"username": {
|
|
"name": "username",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": true,
|
|
"autoincrement": false
|
|
},
|
|
"password_hash": {
|
|
"name": "password_hash",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": true,
|
|
"autoincrement": false
|
|
},
|
|
"role": {
|
|
"name": "role",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": true,
|
|
"autoincrement": false
|
|
},
|
|
"created_at": {
|
|
"name": "created_at",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": true,
|
|
"autoincrement": false,
|
|
"default": "(current_timestamp)"
|
|
}
|
|
},
|
|
"indexes": {
|
|
"users_username_unique": {
|
|
"name": "users_username_unique",
|
|
"columns": [
|
|
"username"
|
|
],
|
|
"isUnique": true
|
|
}
|
|
},
|
|
"foreignKeys": {},
|
|
"compositePrimaryKeys": {},
|
|
"uniqueConstraints": {},
|
|
"checkConstraints": {}
|
|
}
|
|
},
|
|
"views": {},
|
|
"enums": {},
|
|
"_meta": {
|
|
"schemas": {},
|
|
"tables": {},
|
|
"columns": {}
|
|
},
|
|
"internal": {
|
|
"indexes": {}
|
|
}
|
|
} |