Add code resolver, sync conflict handling, and user isolation
Introduce a CodeResolverService to classify user login codes, complete with detailed resolution logic and usability checks. Extend the sync system to handle conflicts via last-write-wins arbitration, with detailed conflict tracking for review. Update file permissions and runtime isolation in Docker to enhance security.
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
-- AlterTable
|
||||
ALTER TABLE "SyncLogEntry" ADD COLUMN "occurredAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP;
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "SyncRecordVersion" (
|
||||
"id" TEXT NOT NULL,
|
||||
"model" TEXT NOT NULL,
|
||||
"recordId" TEXT NOT NULL,
|
||||
"lastWriteAt" TIMESTAMP(3) NOT NULL,
|
||||
"lastWriteOrigin" TEXT NOT NULL,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "SyncRecordVersion_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "SyncConflict" (
|
||||
"id" TEXT NOT NULL,
|
||||
"model" TEXT NOT NULL,
|
||||
"recordId" TEXT NOT NULL,
|
||||
"winningOrigin" TEXT NOT NULL,
|
||||
"losingOrigin" TEXT NOT NULL,
|
||||
"winningPayload" JSONB NOT NULL,
|
||||
"losingPayload" JSONB NOT NULL,
|
||||
"detectedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "SyncConflict_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "SyncRecordVersion_model_recordId_key" ON "SyncRecordVersion"("model", "recordId");
|
||||
+44
-8
@@ -348,15 +348,19 @@ enum SyncOperation {
|
||||
/// Append-only log of local mutations, replicated to the peer server (local
|
||||
/// <-> cloud). `originId` is the SERVER_ID that made the change, so applying
|
||||
/// an incoming entry never gets re-captured/re-pushed back (no echo loops).
|
||||
/// `occurredAt` is the wall-clock moment of the mutation itself (set at
|
||||
/// capture time), distinct from `createdAt` which is just row-insert time -
|
||||
/// conflict resolution compares `occurredAt`, never sync/network timing.
|
||||
model SyncLogEntry {
|
||||
id String @id @default(cuid())
|
||||
sequence Int @default(autoincrement())
|
||||
model String
|
||||
recordId String
|
||||
operation SyncOperation
|
||||
payload Json
|
||||
originId String
|
||||
createdAt DateTime @default(now())
|
||||
id String @id @default(cuid())
|
||||
sequence Int @default(autoincrement())
|
||||
model String
|
||||
recordId String
|
||||
operation SyncOperation
|
||||
payload Json
|
||||
originId String
|
||||
occurredAt DateTime @default(now())
|
||||
createdAt DateTime @default(now())
|
||||
}
|
||||
|
||||
/// Per-peer replication progress, kept on the side that initiates sync
|
||||
@@ -368,3 +372,35 @@ model SyncCursor {
|
||||
lastPushedSequence Int @default(0)
|
||||
lastPulledSequence Int @default(0)
|
||||
}
|
||||
|
||||
/// Last-write-wins register, one row per replicated record. Tracks the
|
||||
/// wall-clock time and origin of whichever mutation - local or remote - is
|
||||
/// currently considered authoritative for that record, so a concurrent edit
|
||||
/// on both servers resolves deterministically by actual edit time instead
|
||||
/// of by sync/network arrival order.
|
||||
model SyncRecordVersion {
|
||||
id String @id @default(cuid())
|
||||
model String
|
||||
recordId String
|
||||
lastWriteAt DateTime
|
||||
lastWriteOrigin String
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@unique([model, recordId])
|
||||
}
|
||||
|
||||
/// Audit trail of detected conflicts: two servers wrote the same record
|
||||
/// within the replication window. Resolution (last-write-wins by
|
||||
/// occurredAt) still happens automatically and immediately - nothing here
|
||||
/// blocks live sync - but Leitungsteam can review afterwards whether a
|
||||
/// discarded edit needs to be manually reapplied.
|
||||
model SyncConflict {
|
||||
id String @id @default(cuid())
|
||||
model String
|
||||
recordId String
|
||||
winningOrigin String
|
||||
losingOrigin String
|
||||
winningPayload Json
|
||||
losingPayload Json
|
||||
detectedAt DateTime @default(now())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user