Add device-certificate mTLS auth, live position tracking, and API docs
Introduces a CA/PKI module so field devices can authenticate to Mosquitto over TLS (8883) with per-device client certificates (CN = serial number) instead of a shared password, with matching Devices/MQTT-Certs UI. Adds live transmitter position tracking alongside logged points, an MQTTS transport option in the simulator for exercising the real cert-auth path, and Swagger API docs at /api/docs. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -142,15 +142,45 @@ model Device {
|
||||
// fetches this via GET /api/devices/:serial/status to show on its own screen.
|
||||
disabledReason String?
|
||||
lastSeenAt DateTime? @db.Timestamptz(6)
|
||||
// Most recent known position, from either a "status" ping (live-only, never
|
||||
// persisted as a LocatePoint) or a "log" point — whichever is newest. Lets
|
||||
// the devices page show current position without waiting for a log write.
|
||||
lastPosition Json?
|
||||
lastPositionAt DateTime? @db.Timestamptz(6)
|
||||
createdAt DateTime @default(now()) @db.Timestamptz(6)
|
||||
updatedAt DateTime @updatedAt @db.Timestamptz(6)
|
||||
|
||||
org Organization @relation(fields: [orgId], references: [id], onDelete: Cascade)
|
||||
points LocatePoint[]
|
||||
org Organization @relation(fields: [orgId], references: [id], onDelete: Cascade)
|
||||
points LocatePoint[]
|
||||
certificate DeviceCertificate?
|
||||
|
||||
@@map("devices")
|
||||
}
|
||||
|
||||
// A client certificate issued to a device for mTLS auth on the broker's 8883
|
||||
// listener; the cert's CN (= serialNumber) becomes the MQTT username. The CA
|
||||
// key/server key never touch the DB (see PkiService) — only device
|
||||
// certs/keys are stored here, mirroring how the reference implementation
|
||||
// (MQTT_DEVICE_AUTH.md) does it. One active cert per device; issuing a new
|
||||
// one requires deleting this row first. No revokedAt: deleting the row is
|
||||
// the only "revoke" action there is, and it isn't broker-enforced either way
|
||||
// (no CRL/OCSP), so a soft-delete flag would misleadingly imply otherwise.
|
||||
model DeviceCertificate {
|
||||
id String @id @default(cuid())
|
||||
deviceId String @unique
|
||||
serialNumber String
|
||||
commonName String
|
||||
certificatePem String @db.Text
|
||||
privateKeyPem String @db.Text
|
||||
fingerprint String
|
||||
issuedAt DateTime @default(now()) @db.Timestamptz(6)
|
||||
expiresAt DateTime @db.Timestamptz(6)
|
||||
|
||||
device Device @relation(fields: [deviceId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@map("device_certificates")
|
||||
}
|
||||
|
||||
model LocatePoint {
|
||||
id BigInt @id @default(autoincrement())
|
||||
jobId String
|
||||
|
||||
Reference in New Issue
Block a user