mirror of
https://github.com/temetro/temetro.git
synced 2026-09-04 14:55:28 +00:00
feat: patient wallet — real Signing, encrypted share relay, import-from-app
Backend - clinic Ed25519 signing key (services/signing.ts, routes/signing.ts, clinic_signing_keys table) — Settings → Signing is now real - @noble wallet-crypto (lib/wallet-crypto.ts): ed25519 identity, base58check wallet numbers, sealed-box (x25519 + xchacha20poly1305) - /wallet Socket.io relay namespace (challenge-signed device auth) forwarding only ciphertext; emitToWallet helper - import-from-app flow (routes/patients-wallet.ts, services/wallet-share.ts): request-share → patient approval → decrypt + verify → review draft → commit - temporary shares: patients.share_expires_at + 5-min auto-delete sweep; revoke Frontend - SigningPanel wired to live key/fingerprint/rotate + shared-records list - "Import from a patient app" dialog (lib/signing.ts, import-from-wallet-dialog) reusing the draft-review path; temporary badge on the patient list Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
CREATE TABLE "clinic_signing_keys" (
|
||||
"organization_id" text PRIMARY KEY NOT NULL,
|
||||
"algorithm" text DEFAULT 'ed25519' NOT NULL,
|
||||
"public_key" text NOT NULL,
|
||||
"fingerprint" text NOT NULL,
|
||||
"private_key_enc" text NOT NULL,
|
||||
"created_at" timestamp DEFAULT now() NOT NULL,
|
||||
"rotated_at" timestamp
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "wallet_share_requests" (
|
||||
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||
"organization_id" text NOT NULL,
|
||||
"requested_by" text NOT NULL,
|
||||
"wallet_number" text NOT NULL,
|
||||
"ephemeral_pub_key" text NOT NULL,
|
||||
"ephemeral_priv_enc" text NOT NULL,
|
||||
"status" text DEFAULT 'pending' NOT NULL,
|
||||
"share_mode" text DEFAULT 'permanent' NOT NULL,
|
||||
"share_expires_at" timestamp,
|
||||
"draft" jsonb,
|
||||
"committed_file_number" text,
|
||||
"created_at" timestamp DEFAULT now() NOT NULL,
|
||||
"resolved_at" timestamp
|
||||
);
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "patients" ADD COLUMN "share_origin" text;--> statement-breakpoint
|
||||
ALTER TABLE "patients" ADD COLUMN "share_expires_at" timestamp;--> statement-breakpoint
|
||||
ALTER TABLE "clinic_signing_keys" ADD CONSTRAINT "clinic_signing_keys_organization_id_organization_id_fk" FOREIGN KEY ("organization_id") REFERENCES "public"."organization"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "wallet_share_requests" ADD CONSTRAINT "wallet_share_requests_organization_id_organization_id_fk" FOREIGN KEY ("organization_id") REFERENCES "public"."organization"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "wallet_share_requests" ADD CONSTRAINT "wallet_share_requests_requested_by_user_id_fk" FOREIGN KEY ("requested_by") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
CREATE INDEX "wallet_share_org_idx" ON "wallet_share_requests" USING btree ("organization_id");--> statement-breakpoint
|
||||
CREATE INDEX "wallet_share_wallet_idx" ON "wallet_share_requests" USING btree ("wallet_number");
|
||||
File diff suppressed because it is too large
Load Diff
@@ -197,6 +197,13 @@
|
||||
"when": 1781973588708,
|
||||
"tag": "0027_romantic_kylun",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 28,
|
||||
"version": "7",
|
||||
"when": 1782052852524,
|
||||
"tag": "0028_military_cyclops",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user