mirror of
https://github.com/saltbo/zpan.git
synced 2026-10-31 02:41:33 +08:00
Three related robustness fixes for the cloud pairing flow: 1. Trusted license public keys are env-configurable (ZPAN_LICENSE_PUBLIC_KEYS) instead of hardcoding dev keys in source — a leaked dev key is rotated via config and never baked into production builds. Registered in all platform factories. 2. Certificate verification surfaces a specific rejection reason (signature/issuer/instance/expired/host), and the pairing modal distinguishes a cert-verification failure from a genuine timeout instead of showing both as "expired". On failure the poll handler rolls back the orphaned cloud binding. 3. After verifying + storing the certificate, the instance confirms the binding to the cloud (zpan-cloud-sdk 2.1.0's POST /licenses/:id/confirm) so the cloud pairing page resolves to success only once the instance actually accepted it. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
33 lines
1.1 KiB
TypeScript
33 lines
1.1 KiB
TypeScript
import Database from 'better-sqlite3'
|
|
import { drizzle } from 'drizzle-orm/better-sqlite3'
|
|
import { migrate } from 'drizzle-orm/better-sqlite3/migrator'
|
|
import * as authSchema from '../db/auth-schema'
|
|
import * as schema from '../db/schema'
|
|
import { registerEnvPublicKeys } from '../licensing/public-keys'
|
|
import type { Platform } from './interface'
|
|
|
|
export function createNodePlatform(): Platform {
|
|
const dbPath = process.env.DATABASE_URL || './zpan.db'
|
|
const migrationsFolder = process.env.MIGRATIONS_DIR || './migrations'
|
|
|
|
const sqlite = new Database(dbPath)
|
|
sqlite.pragma('journal_mode = WAL')
|
|
const db = drizzle(sqlite, { schema: { ...schema, ...authSchema } })
|
|
|
|
migrate(db, { migrationsFolder })
|
|
|
|
registerEnvPublicKeys(process.env.ZPAN_LICENSE_PUBLIC_KEYS)
|
|
|
|
return {
|
|
db,
|
|
getEnv(key: string) {
|
|
return process.env[key]
|
|
},
|
|
// Node has no platform-native bindings — callers always fall back to
|
|
// whatever the non-binding path does (e.g. DB-configured S3 storage).
|
|
getBinding<T = unknown>(_key: string): T | undefined {
|
|
return undefined
|
|
},
|
|
}
|
|
}
|