@everystack/server 0.4.25 → 0.4.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +3 -3
- package/src/plugin.ts +69 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@everystack/server",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.26",
|
|
4
4
|
"description": "Server runtime primitives for Lambda — event adapters, routing, SSR, image processing",
|
|
5
5
|
"license": "AGPL-3.0-only",
|
|
6
6
|
"author": "Scalable Technology, Inc. <licensing@scalable.technology>",
|
|
@@ -186,8 +186,8 @@
|
|
|
186
186
|
"sst": "4.13.1",
|
|
187
187
|
"ts-jest": "29.4.9",
|
|
188
188
|
"typescript": "5.9.3",
|
|
189
|
-
"@everystack/
|
|
190
|
-
"@everystack/
|
|
189
|
+
"@everystack/cli": "0.4.65",
|
|
190
|
+
"@everystack/auth": "0.4.3"
|
|
191
191
|
},
|
|
192
192
|
"scripts": {
|
|
193
193
|
"test": "jest",
|
package/src/plugin.ts
CHANGED
|
@@ -846,6 +846,75 @@ export function dbPlugin(options: DbPluginOptions): Plugin {
|
|
|
846
846
|
};
|
|
847
847
|
|
|
848
848
|
|
|
849
|
+
// --- db:rotate — A/B role detection, provisioning, retirement, draining ---
|
|
850
|
+
// Runs inside the VPC on the operator connection. The CLI orchestrates the
|
|
851
|
+
// AWS side (secret writes, rolling restart, verification) around these calls.
|
|
852
|
+
actions['db:rotate'] = async (payload, _ctx) => {
|
|
853
|
+
const { sql } = await import('drizzle-orm');
|
|
854
|
+
const {
|
|
855
|
+
detectActiveRole,
|
|
856
|
+
provisionInactiveRole,
|
|
857
|
+
retireRole,
|
|
858
|
+
countRoleSessions,
|
|
859
|
+
terminateRoleSessions,
|
|
860
|
+
} = await import('./rotate');
|
|
861
|
+
|
|
862
|
+
const p = (payload ?? {}) as {
|
|
863
|
+
action: 'detect' | 'provision' | 'retire' | 'count-sessions' | 'terminate-sessions' | 'probe-login';
|
|
864
|
+
baseRole?: string;
|
|
865
|
+
password?: string;
|
|
866
|
+
role?: string;
|
|
867
|
+
url?: string;
|
|
868
|
+
};
|
|
869
|
+
|
|
870
|
+
const deps = {
|
|
871
|
+
query: async (s: string) => {
|
|
872
|
+
const rows = await opsDb.execute(sql.raw(s));
|
|
873
|
+
return rows as any[];
|
|
874
|
+
},
|
|
875
|
+
execute: async (s: string) => { await opsDb.execute(sql.raw(s)); },
|
|
876
|
+
};
|
|
877
|
+
|
|
878
|
+
try {
|
|
879
|
+
switch (p.action) {
|
|
880
|
+
case 'detect':
|
|
881
|
+
return await detectActiveRole(p.baseRole ?? 'authenticator', deps);
|
|
882
|
+
case 'provision': {
|
|
883
|
+
if (!p.baseRole || !p.password) return { error: 'baseRole and password required' };
|
|
884
|
+
const slot = await detectActiveRole(p.baseRole, deps);
|
|
885
|
+
if (!slot) return { error: `No rotation pairs for ${p.baseRole}` };
|
|
886
|
+
await provisionInactiveRole(slot, p.password, deps);
|
|
887
|
+
return { ...slot, provisioned: true };
|
|
888
|
+
}
|
|
889
|
+
case 'retire':
|
|
890
|
+
if (!p.role) return { error: 'role required' };
|
|
891
|
+
await retireRole(p.role, deps);
|
|
892
|
+
return { retired: p.role };
|
|
893
|
+
case 'count-sessions':
|
|
894
|
+
if (!p.role) return { error: 'role required' };
|
|
895
|
+
return { count: await countRoleSessions(p.role, deps) };
|
|
896
|
+
case 'terminate-sessions':
|
|
897
|
+
if (!p.role) return { error: 'role required' };
|
|
898
|
+
return { terminated: await terminateRoleSessions(p.role, deps) };
|
|
899
|
+
case 'probe-login': {
|
|
900
|
+
if (!p.url) return { error: 'url required' };
|
|
901
|
+
const { default: postgres } = await import('postgres');
|
|
902
|
+
const probe = postgres(p.url, { max: 1, connect_timeout: 5, ssl: 'prefer' });
|
|
903
|
+
try {
|
|
904
|
+
await probe`SELECT 1`;
|
|
905
|
+
return { connected: true };
|
|
906
|
+
} finally {
|
|
907
|
+
await probe.end({ timeout: 1 });
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
default:
|
|
911
|
+
return { error: `Unknown rotate action: ${p.action}` };
|
|
912
|
+
}
|
|
913
|
+
} catch (err: any) {
|
|
914
|
+
return { error: err?.message || String(err) };
|
|
915
|
+
}
|
|
916
|
+
};
|
|
917
|
+
|
|
849
918
|
// --- db:backups / db:restore — list + restore logical backups ---
|
|
850
919
|
// db:backup and db:export are pg_dump work and now run in the ephemeral Task lane
|
|
851
920
|
// (@everystack/jobs dbTaskPlugin) — the ops Lambda holds no pg binaries. db:backups is a plain
|