feat(release): add reversible production cutover gates
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
import Database from 'better-sqlite3';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { migrateDatabase } from './infrastructure/database/migrations.js';
|
||||
import { createProductionReadiness } from './production-readiness.js';
|
||||
|
||||
function fixture() {
|
||||
const db = new Database(':memory:');
|
||||
migrateDatabase(db);
|
||||
return db;
|
||||
}
|
||||
|
||||
describe('production readiness release gates', () => {
|
||||
it('fails closed on pending credentials, recovery markers, missing assets and configured gateway failure', async () => {
|
||||
const db = fixture();
|
||||
db.prepare(
|
||||
"INSERT INTO app_settings(key,value_json,created_at,updated_at) VALUES('legacyImport.pendingCredentials','2','x','x')",
|
||||
).run();
|
||||
const readiness = createProductionReadiness({
|
||||
db,
|
||||
gatewayToken: 'x'.repeat(32),
|
||||
keychainMetadataCheck: async () => true,
|
||||
assetsCheck: async () => false,
|
||||
recoveryMarkersCheck: async () => 1,
|
||||
upstreamGatewayCheck: async () => false,
|
||||
});
|
||||
await expect(readiness()).resolves.toEqual({
|
||||
ready: false,
|
||||
checks: {
|
||||
database: 'ready',
|
||||
migrations: 'ready',
|
||||
gatewayAuth: 'ready',
|
||||
keychain: 'ready',
|
||||
pendingCredentials: 'pending:2',
|
||||
recoveryMarkers: 'present:1',
|
||||
assets: 'unavailable',
|
||||
upstreamGateway: 'unavailable',
|
||||
},
|
||||
});
|
||||
db.close();
|
||||
});
|
||||
|
||||
it('requires explicit release checks and reports ready only when every gate passes', async () => {
|
||||
const db = fixture();
|
||||
const missing = await createProductionReadiness({
|
||||
db,
|
||||
gatewayToken: 'x'.repeat(32),
|
||||
keychainMetadataCheck: async () => true,
|
||||
})();
|
||||
expect(missing.ready).toBe(false);
|
||||
expect(missing.checks).toMatchObject({
|
||||
assets: 'unconfigured',
|
||||
recoveryMarkers: 'unconfigured',
|
||||
upstreamGateway: 'unconfigured',
|
||||
pendingCredentials: 'ready',
|
||||
});
|
||||
const ready = await createProductionReadiness({
|
||||
db,
|
||||
gatewayToken: 'x'.repeat(32),
|
||||
keychainMetadataCheck: async () => true,
|
||||
assetsCheck: async () => true,
|
||||
recoveryMarkersCheck: async () => 0,
|
||||
upstreamGatewayCheck: async () => true,
|
||||
})();
|
||||
expect(ready.ready).toBe(true);
|
||||
db.close();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user