sporades 0.9.38 โ 0.9.40
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/CHANGES.md +53 -0
- package/Dockerfile.base +5 -5
- package/bin/sporades-host-helper.js +55 -4
- package/bin/sporades.js +82 -15
- package/dist/base-image.js +2 -2
- package/dist/cli/cli-help.d.ts +2 -2
- package/dist/cli/cli-help.d.ts.map +1 -1
- package/dist/cli/cli-help.js +2 -0
- package/dist/cli/cli-help.js.map +1 -1
- package/dist/cli/cli-version.d.ts +1 -1
- package/dist/cli/cli-version.js +1 -1
- package/dist/cli/database-inspection-envelope.d.ts +9 -0
- package/dist/cli/database-inspection-envelope.d.ts.map +1 -0
- package/dist/cli/database-inspection-envelope.js +38 -0
- package/dist/cli/database-inspection-envelope.js.map +1 -0
- package/dist/cli/host-helper-requests.d.ts +12 -2
- package/dist/cli/host-helper-requests.d.ts.map +1 -1
- package/dist/cli/sporades-host-helper.js +26 -1
- package/dist/cli/sporades-host-helper.js.map +1 -1
- package/dist/cli/sporades.js +60 -9
- package/dist/cli/sporades.js.map +1 -1
- package/dist/database-runtime.d.ts.map +1 -1
- package/dist/database-runtime.js +23 -3
- package/dist/database-runtime.js.map +1 -1
- package/dist/generated-source-manifest.json +7 -2
- package/dist/templates/server-bundle-entry.d.ts.map +1 -1
- package/dist/templates/server-bundle-entry.js +49 -2
- package/dist/templates/server-bundle-entry.js.map +1 -1
- package/dist/templates/server-bundle-module-graph.js +1 -1
- package/dist/templates/server-bundle-module-graph.js.map +1 -1
- package/package.json +1 -1
package/CHANGES.md
CHANGED
|
@@ -1,5 +1,58 @@
|
|
|
1
1
|
# Changes
|
|
2
2
|
|
|
3
|
+
## v0.9.40 - 2026-10-23
|
|
4
|
+
|
|
5
|
+
Changes since v0.9.39.
|
|
6
|
+
|
|
7
|
+
### ๐ Documentation
|
|
8
|
+
|
|
9
|
+
- Upgrade Capsule base to Node 24 LTS and normalize npm pack JSON (#288) (8f5ecc5b).
|
|
10
|
+
|
|
11
|
+
### ๐งช Tests
|
|
12
|
+
|
|
13
|
+
- Describe SQLite inspection columns without StatementSync#columns() (#287) (9b29b3d5).
|
|
14
|
+
|
|
15
|
+
## v0.9.39 - 2026-10-22
|
|
16
|
+
|
|
17
|
+
Changes since v0.9.38.
|
|
18
|
+
|
|
19
|
+
### ๐ Features
|
|
20
|
+
|
|
21
|
+
- Add read-only sporades host db list|dump|query (#286) (c9f0d358).
|
|
22
|
+
|
|
23
|
+
## Unreleased
|
|
24
|
+
|
|
25
|
+
### ๐ฆ Packaging
|
|
26
|
+
|
|
27
|
+
- Upgrade the default Capsule Base image to `0.3.0-node24-alpine`, using Node
|
|
28
|
+
24.22.1 LTS on Alpine 3.23 with a pinned upstream image digest. Upgrade the CLI
|
|
29
|
+
and Host helper and redeploy to replace existing containers; restarting a
|
|
30
|
+
release preserves its pinned image. Keep explicit image overrides unchanged.
|
|
31
|
+
- Normalize npm pack JSON metadata across flat and package-keyed formats in
|
|
32
|
+
release verification and packaged compatibility checks, preserving artifact
|
|
33
|
+
hashes and rejecting ambiguous output.
|
|
34
|
+
|
|
35
|
+
### ๐ Features
|
|
36
|
+
|
|
37
|
+
- Add read-only `sporades host db list|dump|query` for running Hosted Capsules (#285).
|
|
38
|
+
It runs the Host helper over the operator's existing SSH access and the
|
|
39
|
+
generated Bundle's one-shot action seam, opens the Capsule SQLite file
|
|
40
|
+
read-only and query-only without stopping the Capsule, and refuses mutating
|
|
41
|
+
SQL both locally and in the runtime. `--json` output matches
|
|
42
|
+
`sporades db list|dump|query --json` against a Dev session. `--subname`
|
|
43
|
+
defaults to the project's Host binding. Requires `sporades host upgrade` and
|
|
44
|
+
a redeploy with this CLI; no public route is added.
|
|
45
|
+
|
|
46
|
+
### ๐ Bug Fixes
|
|
47
|
+
|
|
48
|
+
- Fix `sporades host db query` failing with "columns is not a function" on
|
|
49
|
+
Hosted Capsules. The previous Base image ran Node 22.14, whose `node:sqlite` lacks
|
|
50
|
+
`StatementSync#columns()` (added in 22.16). SQLite inspection queries now
|
|
51
|
+
describe their columns without it, including zero-row results, so Hosted,
|
|
52
|
+
Dev and MCP ops queries on Node 22.13โ22.15 return the same
|
|
53
|
+
`{ ok, data: { columns, rows }, error }` envelope. Requires a redeploy with
|
|
54
|
+
this CLI.
|
|
55
|
+
|
|
3
56
|
## v0.9.38 - 2026-10-22
|
|
4
57
|
|
|
5
58
|
Changes since v0.9.37.
|
package/Dockerfile.base
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
FROM node:22.
|
|
1
|
+
FROM node:24.22.1-alpine3.23@sha256:0468540aa58203ff9e40c2aab3907c52644ab818af6176b1c70a026137dc92a2
|
|
2
2
|
|
|
3
3
|
LABEL org.opencontainers.image.title="Sporades Base Image"
|
|
4
|
-
LABEL org.opencontainers.image.description="Thin Node
|
|
5
|
-
LABEL org.opencontainers.image.version="0.
|
|
4
|
+
LABEL org.opencontainers.image.description="Thin Node 24 LTS Base image for Sporades Container sessions and Hosted Capsules"
|
|
5
|
+
LABEL org.opencontainers.image.version="0.3.0-node24-alpine"
|
|
6
6
|
LABEL org.opencontainers.image.source="https://github.com/sporades/sporades"
|
|
7
7
|
LABEL com.sporades.base-image.name="sporades-base"
|
|
8
|
-
LABEL com.sporades.base-image.version="0.
|
|
9
|
-
LABEL com.sporades.base-image.node="
|
|
8
|
+
LABEL com.sporades.base-image.version="0.3.0-node24-alpine"
|
|
9
|
+
LABEL com.sporades.base-image.node="24"
|
|
10
10
|
|
|
11
11
|
RUN apk add --no-cache openssh-server fail2ban clamav clamav-daemon \
|
|
12
12
|
&& addgroup -g 10001 -S sporades \
|
|
@@ -256,8 +256,8 @@ var init_base_image = __esm({
|
|
|
256
256
|
"use strict";
|
|
257
257
|
SPORADES_BASE_IMAGE = {
|
|
258
258
|
name: "sporades-base",
|
|
259
|
-
image: "ghcr.io/sporades/sporades-base:0.
|
|
260
|
-
version: "0.
|
|
259
|
+
image: "ghcr.io/sporades/sporades-base:0.3.0-node24-alpine",
|
|
260
|
+
version: "0.3.0-node24-alpine",
|
|
261
261
|
runtimeUser: "sporades",
|
|
262
262
|
runtimeUid: 10001,
|
|
263
263
|
runtimeGid: 10001,
|
|
@@ -46183,7 +46183,7 @@ var mutationExecution = new MutationExecutionStorage();
|
|
|
46183
46183
|
init_cli_support();
|
|
46184
46184
|
|
|
46185
46185
|
// src/cli/cli-version.ts
|
|
46186
|
-
var CLI_VERSION = "0.9.
|
|
46186
|
+
var CLI_VERSION = "0.9.40";
|
|
46187
46187
|
|
|
46188
46188
|
// src/cli/schedule-inspection-envelope.ts
|
|
46189
46189
|
var SCHEDULE_DIAGNOSTIC_FIELDS = /* @__PURE__ */ new Set([
|
|
@@ -46258,6 +46258,40 @@ function sanitizeScheduleInspectionEnvelope(envelope, invalid4) {
|
|
|
46258
46258
|
return { ok: true, data: { capsule: { name: envelope.data.capsule.name }, schedules }, error: null };
|
|
46259
46259
|
}
|
|
46260
46260
|
|
|
46261
|
+
// src/cli/database-inspection-envelope.ts
|
|
46262
|
+
var DATABASE_INSPECTION_ACTIONS = ["db.list", "db.dump", "db.query"];
|
|
46263
|
+
var DATABASE_INSPECTION_INPUT_BYTE_LIMIT = 24 * 1024;
|
|
46264
|
+
function encodeDatabaseInspectionInput(sql) {
|
|
46265
|
+
const encoded = Buffer.from(JSON.stringify({ sql }), "utf8").toString("base64url");
|
|
46266
|
+
return encoded.length <= DATABASE_INSPECTION_INPUT_BYTE_LIMIT ? encoded : null;
|
|
46267
|
+
}
|
|
46268
|
+
var DATABASE_INSPECTION_MAX_BUFFER = 128 * 1024 * 1024;
|
|
46269
|
+
function isDatabaseInspectionAction(action) {
|
|
46270
|
+
return DATABASE_INSPECTION_ACTIONS.includes(action);
|
|
46271
|
+
}
|
|
46272
|
+
function sanitizeDatabaseInspectionEnvelope(action, envelope, invalid4) {
|
|
46273
|
+
const data2 = envelope?.data;
|
|
46274
|
+
if (envelope?.ok === true && data2 && typeof data2 === "object" && !Array.isArray(data2)) {
|
|
46275
|
+
if (action === "db.query" && Array.isArray(data2.columns) && Array.isArray(data2.rows)) {
|
|
46276
|
+
return { ok: true, data: { columns: data2.columns, rows: data2.rows }, error: null };
|
|
46277
|
+
}
|
|
46278
|
+
if (action !== "db.query" && Array.isArray(data2.tables)) {
|
|
46279
|
+
return { ok: true, data: { tables: data2.tables }, error: null };
|
|
46280
|
+
}
|
|
46281
|
+
}
|
|
46282
|
+
if (envelope?.ok === false && typeof envelope.error?.message === "string") {
|
|
46283
|
+
return {
|
|
46284
|
+
ok: false,
|
|
46285
|
+
data: null,
|
|
46286
|
+
error: {
|
|
46287
|
+
message: envelope.error.message,
|
|
46288
|
+
hint: typeof envelope.error.hint === "string" ? envelope.error.hint : "Check the SQL and retry the command."
|
|
46289
|
+
}
|
|
46290
|
+
};
|
|
46291
|
+
}
|
|
46292
|
+
return invalid4();
|
|
46293
|
+
}
|
|
46294
|
+
|
|
46261
46295
|
// src/cli/host-helper-archive.ts
|
|
46262
46296
|
import { spawnSync } from "node:child_process";
|
|
46263
46297
|
import { readFileSync } from "node:fs";
|
|
@@ -48806,6 +48840,10 @@ async function dispatchMain(request2) {
|
|
|
48806
48840
|
runCapsuleAccessKeyAction(request2);
|
|
48807
48841
|
return;
|
|
48808
48842
|
}
|
|
48843
|
+
if (isDatabaseInspectionAction(request2.action)) {
|
|
48844
|
+
inspectCapsuleDatabase(request2);
|
|
48845
|
+
return;
|
|
48846
|
+
}
|
|
48809
48847
|
if (request2.action === "host.stats") {
|
|
48810
48848
|
await statsHost(request2);
|
|
48811
48849
|
return;
|
|
@@ -48852,6 +48890,19 @@ function runCapsuleAccessKeyAction(request2) {
|
|
|
48852
48890
|
Buffer.from(JSON.stringify(accessKeys), "utf8").toString("base64url")
|
|
48853
48891
|
]);
|
|
48854
48892
|
}
|
|
48893
|
+
function inspectCapsuleDatabase(request2) {
|
|
48894
|
+
const action = request2.action;
|
|
48895
|
+
if (!isDatabaseInspectionAction(action)) throw helperError("Unsupported Host helper action.", "Update the Host helper or use a supported Sporades host command.");
|
|
48896
|
+
const exactKeys2 = (value, keys2) => Object.keys(value).length === keys2.length && Object.keys(value).every((key) => keys2.includes(key));
|
|
48897
|
+
const query = action === "db.query";
|
|
48898
|
+
const sql = request2.db?.sql;
|
|
48899
|
+
if (!exactKeys2(request2, query ? ["action", "host", "capsule", "db"] : ["action", "host", "capsule"]) || !request2.host || typeof request2.host !== "object" || Array.isArray(request2.host) || !exactKeys2(request2.host, ["alias", "domain", "scheme", "remoteRoot"]) || !request2.capsule || typeof request2.capsule !== "object" || Array.isArray(request2.capsule) || !exactKeys2(request2.capsule, ["subname"]) || query && (!exactKeys2(request2.db ?? {}, ["sql"]) || typeof sql !== "string" || !encodeDatabaseInspectionInput(sql))) {
|
|
48900
|
+
throw helperError("Invalid Hosted database inspection request.", "Upgrade the local Sporades CLI and Host helper together.");
|
|
48901
|
+
}
|
|
48902
|
+
inspectCapsuleRuntime(request2, action, "database", (envelope) => sanitizeDatabaseInspectionEnvelope(action, envelope, () => {
|
|
48903
|
+
throw helperError("Hosted database inspection returned an invalid response.", "Run `sporades host upgrade`, redeploy the Capsule, and retry the command.");
|
|
48904
|
+
}), query ? ["--sporades-action-input", encodeDatabaseInspectionInput(sql)] : []);
|
|
48905
|
+
}
|
|
48855
48906
|
function inspectCapsuleRuntime(request2, action, label, sanitize = (envelope) => envelope, extraArgs = [], preserveBoundedDiagnostics = false) {
|
|
48856
48907
|
const containerName = createHostedContainerName(request2.host.domain, request2.capsule.subname);
|
|
48857
48908
|
if (!checkContainerRunning(containerName)) {
|
|
@@ -48860,7 +48911,7 @@ function inspectCapsuleRuntime(request2, action, label, sanitize = (envelope) =>
|
|
|
48860
48911
|
throw error;
|
|
48861
48912
|
}
|
|
48862
48913
|
const result = runDocker(["exec", containerName, "node", "/app/server.mjs", "--sporades-action", action, ...extraArgs], {
|
|
48863
|
-
maxBuffer: label === "Access-key" ? ACCESS_KEY_OPERATOR_PROCESS_MAX_BUFFER : void 0
|
|
48914
|
+
maxBuffer: label === "Access-key" ? ACCESS_KEY_OPERATOR_PROCESS_MAX_BUFFER : label === "database" ? DATABASE_INSPECTION_MAX_BUFFER : void 0
|
|
48864
48915
|
});
|
|
48865
48916
|
let envelope;
|
|
48866
48917
|
try {
|
package/bin/sporades.js
CHANGED
|
@@ -124294,7 +124294,7 @@ function createSharedDatabaseAdapterMethods(dialect) {
|
|
|
124294
124294
|
(columnMetadata) => thenIfPromise(statement.all(), (allRows) => ({
|
|
124295
124295
|
ok: true,
|
|
124296
124296
|
data: {
|
|
124297
|
-
columns: columnMetadata
|
|
124297
|
+
columns: columnMetadata?.map((column) => column.name) ?? Object.keys(allRows[0] ?? {}),
|
|
124298
124298
|
rows: allRows.filter((row) => !isInternalLogIndexMetadataRow(row, sql3))
|
|
124299
124299
|
},
|
|
124300
124300
|
error: null
|
|
@@ -124315,6 +124315,19 @@ function createSharedDatabaseAdapterMethods(dialect) {
|
|
|
124315
124315
|
}
|
|
124316
124316
|
};
|
|
124317
124317
|
}
|
|
124318
|
+
function describeSqliteColumns(connection, statement, sql2) {
|
|
124319
|
+
if (typeof statement.columns === "function") return statement.columns();
|
|
124320
|
+
let row;
|
|
124321
|
+
try {
|
|
124322
|
+
row = connection.prepare(
|
|
124323
|
+
`SELECT __sporades_columns.* FROM (SELECT 1) LEFT JOIN (${sqlWithoutTrailingTerminator(sql2)}
|
|
124324
|
+
) AS __sporades_columns ON 1 LIMIT 1`
|
|
124325
|
+
).get();
|
|
124326
|
+
} catch {
|
|
124327
|
+
return null;
|
|
124328
|
+
}
|
|
124329
|
+
return Object.keys(row ?? {}).map((name2) => ({ name: name2 }));
|
|
124330
|
+
}
|
|
124318
124331
|
async function createSqliteDatabaseAdapter(databasePath, options = {}) {
|
|
124319
124332
|
const { DatabaseSync } = await import("node:sqlite");
|
|
124320
124333
|
const path24 = await import("node:path");
|
|
@@ -124365,7 +124378,7 @@ async function createSqliteDatabaseAdapter(databasePath, options = {}) {
|
|
|
124365
124378
|
}));
|
|
124366
124379
|
},
|
|
124367
124380
|
columns() {
|
|
124368
|
-
return run2(() => useConnection(() => connection.prepare(sql2)
|
|
124381
|
+
return run2(() => useConnection(() => describeSqliteColumns(connection, connection.prepare(sql2), sql2)));
|
|
124369
124382
|
}
|
|
124370
124383
|
};
|
|
124371
124384
|
}
|
|
@@ -124417,7 +124430,7 @@ async function createSqliteDatabaseAdapter(databasePath, options = {}) {
|
|
|
124417
124430
|
recordLiveQueryStatementWrite(sql2, result);
|
|
124418
124431
|
return result;
|
|
124419
124432
|
},
|
|
124420
|
-
columns: () => statement
|
|
124433
|
+
columns: () => describeSqliteColumns(dedicated, statement, sql2)
|
|
124421
124434
|
});
|
|
124422
124435
|
}
|
|
124423
124436
|
};
|
|
@@ -133948,8 +133961,8 @@ function errorCode2(error) {
|
|
|
133948
133961
|
// src/base-image.ts
|
|
133949
133962
|
var SPORADES_BASE_IMAGE = {
|
|
133950
133963
|
name: "sporades-base",
|
|
133951
|
-
image: "ghcr.io/sporades/sporades-base:0.
|
|
133952
|
-
version: "0.
|
|
133964
|
+
image: "ghcr.io/sporades/sporades-base:0.3.0-node24-alpine",
|
|
133965
|
+
version: "0.3.0-node24-alpine",
|
|
133953
133966
|
runtimeUser: "sporades",
|
|
133954
133967
|
runtimeUid: 10001,
|
|
133955
133968
|
runtimeGid: 10001,
|
|
@@ -149965,6 +149978,8 @@ Capsule commands:
|
|
|
149965
149978
|
Restore a stopped Capsule; optionally --to-subname <destination>
|
|
149966
149979
|
backup status Report last successful backup age for each Capsule
|
|
149967
149980
|
bind <subname> Bind this project to a Hosted Capsule
|
|
149981
|
+
db list|dump|query <sql> [--subname <name>]
|
|
149982
|
+
Read a running Hosted Capsule's database over SSH
|
|
149968
149983
|
register <subname> Register a Hosted Capsule
|
|
149969
149984
|
canonical set <subname> <alias>|clear <subname>
|
|
149970
149985
|
Select the public origin; restart a running Capsule
|
|
@@ -150849,6 +150864,18 @@ function sanitizeScheduleInspectionEnvelope(envelope, invalid4) {
|
|
|
150849
150864
|
return { ok: true, data: { capsule: { name: envelope.data.capsule.name }, schedules }, error: null };
|
|
150850
150865
|
}
|
|
150851
150866
|
|
|
150867
|
+
// src/cli/database-inspection-envelope.ts
|
|
150868
|
+
var DATABASE_INSPECTION_ACTIONS = ["db.list", "db.dump", "db.query"];
|
|
150869
|
+
var DATABASE_INSPECTION_INPUT_BYTE_LIMIT = 24 * 1024;
|
|
150870
|
+
function encodeDatabaseInspectionInput(sql2) {
|
|
150871
|
+
const encoded = Buffer.from(JSON.stringify({ sql: sql2 }), "utf8").toString("base64url");
|
|
150872
|
+
return encoded.length <= DATABASE_INSPECTION_INPUT_BYTE_LIMIT ? encoded : null;
|
|
150873
|
+
}
|
|
150874
|
+
var DATABASE_INSPECTION_MAX_BUFFER = 128 * 1024 * 1024;
|
|
150875
|
+
function isDatabaseInspectionAction(action) {
|
|
150876
|
+
return DATABASE_INSPECTION_ACTIONS.includes(action);
|
|
150877
|
+
}
|
|
150878
|
+
|
|
150852
150879
|
// src/cli/server-env-check.ts
|
|
150853
150880
|
import path20 from "node:path";
|
|
150854
150881
|
async function readProjectServerEnv(projectDir) {
|
|
@@ -153035,7 +153062,7 @@ jobs:
|
|
|
153035
153062
|
}
|
|
153036
153063
|
|
|
153037
153064
|
// src/cli/cli-version.ts
|
|
153038
|
-
var CLI_VERSION = "0.9.
|
|
153065
|
+
var CLI_VERSION = "0.9.40";
|
|
153039
153066
|
|
|
153040
153067
|
// src/cli/sporades.ts
|
|
153041
153068
|
var SUPPORTED_TEMPLATES = new Set(CLIENT_TEMPLATES);
|
|
@@ -154261,7 +154288,7 @@ function parseHostArgs(args) {
|
|
|
154261
154288
|
force = true;
|
|
154262
154289
|
break;
|
|
154263
154290
|
default:
|
|
154264
|
-
if (arg.startsWith("--")) {
|
|
154291
|
+
if (arg.startsWith("--") && subcommand !== "db") {
|
|
154265
154292
|
throw commandError2(
|
|
154266
154293
|
`Unknown flag: ${arg}`,
|
|
154267
154294
|
"Use `sporades host add`, `sporades host use`, `sporades host current`, `sporades host health`, `sporades host bind`, `sporades host register`, `sporades host rotate-key`, `sporades host unregister`, `sporades host delete`, `sporades host push`, `sporades host bootstrap`, `sporades host upgrade`, `sporades host list`, `sporades host releases`, `sporades host rollback`, `sporades host reconcile`, `sporades host stats`, `sporades host logs`, or `sporades host invoke`."
|
|
@@ -154437,6 +154464,16 @@ function parseHostArgs(args) {
|
|
|
154437
154464
|
validateCapsuleSubname(subname);
|
|
154438
154465
|
return { subcommand, ...parsePolicyOperation(positional), hostAlias, subname, json: json2, projectDir: process.cwd() };
|
|
154439
154466
|
}
|
|
154467
|
+
case "db": {
|
|
154468
|
+
const [operation, ...sqlParts] = positional;
|
|
154469
|
+
const usage = "Use `sporades host db list`, `sporades host db dump`, or `sporades host db query <sql>`, with optional `--subname <name> --host <alias>`.";
|
|
154470
|
+
if (!["list", "dump", "query"].includes(operation)) throw commandError2(`Unknown host db command: ${operation ?? ""}`.trim(), usage);
|
|
154471
|
+
if (operation !== "query" && sqlParts.length > 0) throw commandError2("Too many positional arguments.", `Use \`sporades host db ${operation} --json\`.`);
|
|
154472
|
+
if (operation === "query" && sqlParts.length === 0) throw commandError2("Missing SQL query.", "Use `sporades host db query <sql>`.");
|
|
154473
|
+
if (hostAlias) validateHostAlias(hostAlias);
|
|
154474
|
+
if (subname) validateCapsuleSubname(subname);
|
|
154475
|
+
return { subcommand, operation, ...operation === "query" ? { sql: sqlParts.join(" ") } : {}, subname, hostAlias, json: json2, projectDir: process.cwd() };
|
|
154476
|
+
}
|
|
154440
154477
|
case "jobs":
|
|
154441
154478
|
if (positional.length > 0) throw commandError2("Too many positional arguments.", "Use `sporades host jobs --host <alias> --subname <name>`.");
|
|
154442
154479
|
if (!hostAlias) throw commandError2("Missing Host profile alias.", "Pass `--host <alias>`.");
|
|
@@ -156856,6 +156893,31 @@ async function manageHost(options) {
|
|
|
156856
156893
|
writeResult(result, !result.ok);
|
|
156857
156894
|
return;
|
|
156858
156895
|
}
|
|
156896
|
+
case "db": {
|
|
156897
|
+
if (options.operation === "query") {
|
|
156898
|
+
assertReadOnlyInspectionSql(options.sql);
|
|
156899
|
+
if (!encodeDatabaseInspectionInput(options.sql)) {
|
|
156900
|
+
throw commandError2("SQL query is too large for Hosted inspection.", "Keep `sporades host db query` SQL under about 16 KiB.");
|
|
156901
|
+
}
|
|
156902
|
+
}
|
|
156903
|
+
const config = await readHostConfig();
|
|
156904
|
+
const target = await resolveHostPushTarget(config, options);
|
|
156905
|
+
let result = invokeRemoteHostHelper({
|
|
156906
|
+
alias: target.alias,
|
|
156907
|
+
profile: target.profile,
|
|
156908
|
+
action: `db.${options.operation}`,
|
|
156909
|
+
subname: target.subname,
|
|
156910
|
+
projectDir: options.projectDir,
|
|
156911
|
+
...options.operation === "query" ? { db: { sql: options.sql } } : {}
|
|
156912
|
+
});
|
|
156913
|
+
if (!result.ok && /Unsupported Host helper action/i.test(result.error.message)) {
|
|
156914
|
+
result = { ok: false, data: null, error: { code: "HOST_HELPER_UPGRADE_REQUIRED", message: "The Host server CLI does not support database inspection.", hint: `Run \`sporades host upgrade --host ${target.alias}\`, then retry the command.` } };
|
|
156915
|
+
} else if (!result.ok && /Unsupported Sporades runtime action/i.test(result.error.message)) {
|
|
156916
|
+
result = { ok: false, data: null, error: { code: "HOSTED_BUNDLE_UPGRADE_REQUIRED", message: "The Hosted Capsule's Bundle does not support database inspection.", hint: `Redeploy it with this CLI (\`sporades host push --restart --host ${target.alias}\`), then retry the command.` } };
|
|
156917
|
+
}
|
|
156918
|
+
printDatabaseInspection(options.operation, result, options.json);
|
|
156919
|
+
return;
|
|
156920
|
+
}
|
|
156859
156921
|
case "jobs": {
|
|
156860
156922
|
const config = await readHostConfig();
|
|
156861
156923
|
const resolved = resolveHostProfile(config, options.hostAlias);
|
|
@@ -158196,21 +158258,24 @@ function inspectedSshPort(inspected) {
|
|
|
158196
158258
|
return Number.isInteger(port) ? { host: entry.HostIp ?? null, port } : null;
|
|
158197
158259
|
}
|
|
158198
158260
|
async function inspectDatabase(options) {
|
|
158199
|
-
if (options.subcommand === "query")
|
|
158200
|
-
|
|
158201
|
-
|
|
158202
|
-
|
|
158203
|
-
|
|
158261
|
+
if (options.subcommand === "query") assertReadOnlyInspectionSql(options.sql);
|
|
158262
|
+
printDatabaseInspection(options.subcommand, await fetchInspectionDatabase(options), options.json);
|
|
158263
|
+
}
|
|
158264
|
+
function assertReadOnlyInspectionSql(sql2) {
|
|
158265
|
+
const validation = validateReadOnlyInspectionSql(sql2);
|
|
158266
|
+
if (!validation.ok) {
|
|
158267
|
+
throw commandError2(validation.error.message, validation.error.hint);
|
|
158204
158268
|
}
|
|
158205
|
-
|
|
158206
|
-
|
|
158269
|
+
}
|
|
158270
|
+
function printDatabaseInspection(subcommand, result, json2) {
|
|
158271
|
+
if (json2) {
|
|
158207
158272
|
writeResult(result, !result.ok);
|
|
158208
158273
|
return;
|
|
158209
158274
|
}
|
|
158210
158275
|
if (!result.ok) {
|
|
158211
158276
|
throw commandError2(result.error.message, result.error.hint);
|
|
158212
158277
|
}
|
|
158213
|
-
switch (
|
|
158278
|
+
switch (subcommand) {
|
|
158214
158279
|
case "list":
|
|
158215
158280
|
for (const table of result.data.tables) {
|
|
158216
158281
|
process.stdout.write(`${table}
|
|
@@ -158859,6 +158924,7 @@ function invokeRemoteHostHelper(options) {
|
|
|
158859
158924
|
if (options.accessKeys) {
|
|
158860
158925
|
request.accessKeys = options.accessKeys;
|
|
158861
158926
|
}
|
|
158927
|
+
if (options.db) request.db = options.db;
|
|
158862
158928
|
if (options.verification) {
|
|
158863
158929
|
request.verification = options.verification;
|
|
158864
158930
|
}
|
|
@@ -158876,6 +158942,7 @@ function invokeRemoteHostHelper(options) {
|
|
|
158876
158942
|
encoding: "utf8",
|
|
158877
158943
|
...String(options.action).startsWith("access-keys.") ? { maxBuffer: ACCESS_KEY_OPERATOR_PROCESS_MAX_BUFFER } : {},
|
|
158878
158944
|
...String(options.action).includes(".backup.") ? { maxBuffer: 16 * 1024 * 1024 } : {},
|
|
158945
|
+
...isDatabaseInspectionAction(options.action) ? { maxBuffer: DATABASE_INSPECTION_MAX_BUFFER } : {},
|
|
158879
158946
|
input: `${JSON.stringify(request)}
|
|
158880
158947
|
`
|
|
158881
158948
|
});
|
package/dist/base-image.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export const SPORADES_BASE_IMAGE = {
|
|
2
2
|
name: "sporades-base",
|
|
3
|
-
image: "ghcr.io/sporades/sporades-base:0.
|
|
4
|
-
version: "0.
|
|
3
|
+
image: "ghcr.io/sporades/sporades-base:0.3.0-node24-alpine",
|
|
4
|
+
version: "0.3.0-node24-alpine",
|
|
5
5
|
runtimeUser: "sporades",
|
|
6
6
|
runtimeUid: 10001,
|
|
7
7
|
runtimeGid: 10001,
|
package/dist/cli/cli-help.d.ts
CHANGED
|
@@ -25,7 +25,7 @@ Options:
|
|
|
25
25
|
readonly monitoring: "Usage: sporades monitoring stack <init|validate|upgrade|rollback|backup|restore> [options]\n sporades monitoring sender <issue|rotate|commit|cancel|revoke|export|status|legacy-revoke> [options]\n\nGenerate or inspect the versioned trace stack from an installed Sporades package.\nInitialization creates a reviewable directory; it does not start services.\nSender operations run locally on the Monitoring server; results contain no secrets.\nRotation stages a second generation; commit retires the old one after sender verification.\n\nOptions:\n --dir <path> Target stack directory (default: current directory)\n --backup <path> Protected cold snapshot directory (backup/restore)\n --baseline <path> Trusted prior release assets for a schema-3 upgrade\n --sender <name> Named sender for lifecycle operations (optional for status)\n --host <identity> Exact inventory Host scope (issue or legacy-revoke only)\n --out <path> New mode-0600 credential handoff file (export only)\n --generation <n> Verified pending generation to activate (commit only)\n --ingest Disable shared legacy ingestion (legacy-revoke only)\n --json Write { ok, data, error } JSON output\n --help, -h Show this help\n";
|
|
26
26
|
readonly telemetry: "Usage: sporades telemetry profile <add|list|show|remove> [name] [options]\n\nRegister and inspect operator-owned OTLP/HTTP Telemetry profiles. Descriptors store only\ncredential environment and private CA file references; they never store secret values.\nDev sessions use --telemetry <name> first, then sporades.json telemetry.profile, then no export.\n\nOptions for profile add:\n --endpoint <url> OTLP/HTTP base origin (HTTPS, or HTTP loopback with --loopback)\n --dashboard <url> Optional dashboard HTTPS URL\n --credential-env <KEY> Environment variable containing the ingestion bearer token\n --inventory-credential-env <KEY> Exact Host-scoped lifecycle inventory token\n --inventory-host <id> Stable inventory identity (default: first connected domain)\n --metrics-interval-ms <N> Metrics export period, 5000-300000 ms (default 15000)\n --trace-propagation-origin <origin> Approve exact fetch origin (repeatable, max 32)\n --event-loop-delay-resolution-ms <N> Delay timer precision, 10-1000 ms (default 20)\n --ca-file <path> Absolute private CA certificate path for verified TLS\n --loopback Permit a local HTTP collector for development\n --json Write { ok, data, error } JSON output\n --help, -h Show this help\n";
|
|
27
27
|
readonly deploy: "Usage: sporades deploy [status|stop|restart|reconcile|remove|reset|ssh] [options]\n\nStart and manage a local Container session.\n\nCommands:\n deploy Start a local Container session\n deploy status Print Container session status\n deploy stop Stop the running Container session\n deploy restart Restart the running Container session\n deploy policy publish <file>|remove\n Publish or remove the declared admission policy\n deploy reconcile Settle an interrupted deployment-file attempt\n deploy ssh Inspect effective Container SSH access\n deploy remove Remove the Container session\n deploy reset Remove the Container session and local container state\n\nOptions:\n --port <number> Published local port when starting\n --telemetry <name> Export HTTP traces using a registered Telemetry profile\n --no-telemetry Disable export for this Container session\n --force Replace stale or conflicting container state when starting\n --json Write JSON output\n --help, -h Show this help\n";
|
|
28
|
-
readonly host: "Usage: sporades host <command> [options]\n\nManage Host profiles and Hosted Capsules.\n\nProfile commands:\n add <alias> Add a Host profile\n use <alias> Set the default Host profile\n current Print the selected Host profile\n bootstrap Provision the remote Host server\n upgrade Copy the local Host helper to the Host server\n health [subname] Check Host server or Hosted Capsule health\n services enable|disable|uninstall|status observability [--on <alias>]\n Manage pinned GlitchTip and Umami (opt-in)\n services connect <subname> [--host <Capsule-host>] [--on <ops-host>]\n Seal configured error/analytics env; push to activate\n services backup|backups observability [--on <alias>]\n Snapshot or list service databases using Host backup policy\n services restore observability --id <snapshot> --confirm observability\n Restore disabled services; enable again after inspection\n telemetry connect|migrate|reconcile|status|check\n telemetry inventory-export|inventory-reconcile\n Manage the shared Host Telemetry relay\n telemetry exports-disable|remove-agents\n Disable exports; remove agents after inventory acknowledgement\n telemetry resources-enable|resources-disable|resources-remove\n Manage Host OS and Caddy collection independently of Capsules\n telemetry enable|disable <subname>\n Change a Hosted Capsule's Telemetry opt-out\n\nCapsule commands:\n backup configure --file <policy.json>\n Configure encrypted backups and an optional Host timer\n backup create|list|prune --subname <name>\n Manage encrypted SQLite and files snapshots\n backup restore --subname <source> --id <full-id> --confirm <destination>\n Restore a stopped Capsule; optionally --to-subname <destination>\n backup status Report last successful backup age for each Capsule\n bind <subname> Bind this project to a Hosted Capsule\n register <subname> Register a Hosted Capsule\n canonical set <subname> <alias>|clear <subname>\n Select the public origin; restart a running Capsule\n push Push and install a Hosted Capsule release\n start <subname> Start a Hosted Capsule\n stop <subname> Stop a Hosted Capsule\n restart <subname> Restart a Hosted Capsule\n policy publish <file>|remove --host <alias> --subname <name>\n Publish or remove the recorded admission policy\n reconcile <subname> Settle an interrupted deployment-file attempt\n ssh [subname] Inspect effective Hosted Capsule SSH access\n stats [subname] Print Host server or Hosted Capsule stats\n logs [source] Print Hosted Capsule logs\n releases <subname> List Hosted Capsule releases\n rollback <subname> <release-id>\n Roll back to a previous release\n rotate-key <subname>\n Rotate Hosted Capsule Sealed Server env keys\n unregister <subname>\n Unregister a Hosted Capsule\n delete <subname> Delete Hosted Capsule storage\n\nOther commands:\n list List Hosted Capsules\n github workflow write\n Write a GitHub Actions deploy workflow\n invoke <action> Invoke a low-level remote Host helper action\n\nOptions:\n --host <alias> Host profile alias\n --profile <name> Verified HTTPS Telemetry profile for connect or migrate\n --query-credential-env <name>\n Ephemeral operator user:password for check or migrate\n --server <target> SSH target for host add\n --domain <domain> Hosted domain for host add\n --canonical-domain <hostname>\n Public HTTPS link origin for register\n --alias-domain <hostname>\n Custom HTTPS domain for register (repeatable)\n --remote-root <path>\n Remote root path for host add\n --tls <mode> TLS mode: automatic or cloudflare-origin\n --subname <name> Hosted Capsule subname\n --lines <n>, -n <n> Log line count\n --allow-missing-env Push despite missing required Server env keys\n --restart Restart after host push\n --verify Verify release health after host push\n --fallback-to-previous-release\n Roll back when verified push fails\n --branch <name> GitHub workflow branch\n --file <path> GitHub workflow output path\n --dry-run Print workflow without writing it\n --force Overwrite workflow output when writing it\n --json Write JSON output\n --help, -h Show this help\n";
|
|
28
|
+
readonly host: "Usage: sporades host <command> [options]\n\nManage Host profiles and Hosted Capsules.\n\nProfile commands:\n add <alias> Add a Host profile\n use <alias> Set the default Host profile\n current Print the selected Host profile\n bootstrap Provision the remote Host server\n upgrade Copy the local Host helper to the Host server\n health [subname] Check Host server or Hosted Capsule health\n services enable|disable|uninstall|status observability [--on <alias>]\n Manage pinned GlitchTip and Umami (opt-in)\n services connect <subname> [--host <Capsule-host>] [--on <ops-host>]\n Seal configured error/analytics env; push to activate\n services backup|backups observability [--on <alias>]\n Snapshot or list service databases using Host backup policy\n services restore observability --id <snapshot> --confirm observability\n Restore disabled services; enable again after inspection\n telemetry connect|migrate|reconcile|status|check\n telemetry inventory-export|inventory-reconcile\n Manage the shared Host Telemetry relay\n telemetry exports-disable|remove-agents\n Disable exports; remove agents after inventory acknowledgement\n telemetry resources-enable|resources-disable|resources-remove\n Manage Host OS and Caddy collection independently of Capsules\n telemetry enable|disable <subname>\n Change a Hosted Capsule's Telemetry opt-out\n\nCapsule commands:\n backup configure --file <policy.json>\n Configure encrypted backups and an optional Host timer\n backup create|list|prune --subname <name>\n Manage encrypted SQLite and files snapshots\n backup restore --subname <source> --id <full-id> --confirm <destination>\n Restore a stopped Capsule; optionally --to-subname <destination>\n backup status Report last successful backup age for each Capsule\n bind <subname> Bind this project to a Hosted Capsule\n db list|dump|query <sql> [--subname <name>]\n Read a running Hosted Capsule's database over SSH\n register <subname> Register a Hosted Capsule\n canonical set <subname> <alias>|clear <subname>\n Select the public origin; restart a running Capsule\n push Push and install a Hosted Capsule release\n start <subname> Start a Hosted Capsule\n stop <subname> Stop a Hosted Capsule\n restart <subname> Restart a Hosted Capsule\n policy publish <file>|remove --host <alias> --subname <name>\n Publish or remove the recorded admission policy\n reconcile <subname> Settle an interrupted deployment-file attempt\n ssh [subname] Inspect effective Hosted Capsule SSH access\n stats [subname] Print Host server or Hosted Capsule stats\n logs [source] Print Hosted Capsule logs\n releases <subname> List Hosted Capsule releases\n rollback <subname> <release-id>\n Roll back to a previous release\n rotate-key <subname>\n Rotate Hosted Capsule Sealed Server env keys\n unregister <subname>\n Unregister a Hosted Capsule\n delete <subname> Delete Hosted Capsule storage\n\nOther commands:\n list List Hosted Capsules\n github workflow write\n Write a GitHub Actions deploy workflow\n invoke <action> Invoke a low-level remote Host helper action\n\nOptions:\n --host <alias> Host profile alias\n --profile <name> Verified HTTPS Telemetry profile for connect or migrate\n --query-credential-env <name>\n Ephemeral operator user:password for check or migrate\n --server <target> SSH target for host add\n --domain <domain> Hosted domain for host add\n --canonical-domain <hostname>\n Public HTTPS link origin for register\n --alias-domain <hostname>\n Custom HTTPS domain for register (repeatable)\n --remote-root <path>\n Remote root path for host add\n --tls <mode> TLS mode: automatic or cloudflare-origin\n --subname <name> Hosted Capsule subname\n --lines <n>, -n <n> Log line count\n --allow-missing-env Push despite missing required Server env keys\n --restart Restart after host push\n --verify Verify release health after host push\n --fallback-to-previous-release\n Roll back when verified push fails\n --branch <name> GitHub workflow branch\n --file <path> GitHub workflow output path\n --dry-run Print workflow without writing it\n --force Overwrite workflow output when writing it\n --json Write JSON output\n --help, -h Show this help\n";
|
|
29
29
|
readonly logs: "Usage: sporades logs [tail] [options]\n\nPrint Dev session logs.\n\nCommands:\n logs Print recent Dev session logs\n logs tail Follow Dev session logs\n\nOptions:\n --port <number> Target Dev session or local Container port\n --json Write JSON output\n --help, -h Show this help\n";
|
|
30
30
|
readonly db: "Usage: sporades db <command> [options]\n\nInspect the Dev session database.\n\nCommands:\n list List database tables\n dump Dump database contents\n query <sql> Run a read-only SQL query\n\nOptions:\n --port <number> Target Dev session or local Container port\n --json Write JSON output\n --help, -h Show this help\n";
|
|
31
31
|
readonly default: "Usage: sporades <command> [options]\n \n Commands:\n stripe-fake Run the local Team Billing test provider\n create <name> Scaffold a new Capsule\n dev Start a local Dev session\n auth Manage local auth configuration and simulation\n access-keys Inspect and retire Access keys through a running Capsule\n security Inspect effective Capsule security policy\n doctor Run read-only Sporades diagnostics\n env Manage Sealed Server env\n monitoring Generate and validate a monitoring stack\n telemetry Register operator Telemetry profiles\n deploy Start a local Container session\n host Manage Host profiles and Hosted Capsules\n logs Print Dev session logs\n db Inspect the Dev session database\n \n Options:\n --help, -h Show help for command\n --version, -v Show CLI version\n --host <alias> Show Host server CLI version with --version\n --json Write JSON output when supported by the command\n ";
|
|
@@ -46,6 +46,6 @@ Options:
|
|
|
46
46
|
--no-git Skip git initialization
|
|
47
47
|
--json Write JSON output
|
|
48
48
|
--help, -h Show this help
|
|
49
|
-
` | "Usage: sporades dev [status|stop|reset] [options]\n\nStart and manage a local Dev session.\n\nCommands:\n dev Start a Dev session\n dev status Print Dev session status\n dev stop Stop the running Dev session\n dev reset Stop the Dev session and remove local Dev state\n\nOptions:\n --port <number> Dev session port when starting\n --public Allow non-localhost access when starting\n --telemetry <name> Export HTTP traces using a registered Telemetry profile\n --json Write JSON output\n --help, -h Show this help\n" | "Usage: sporades auth <command> [options]\n\nManage local auth configuration and identity simulation.\n\nCommands:\n status Print auth provider status\n clients List connected Dev session clients\n set <provider> Configure or disable anonymous, email, Google, Microsoft, Apple, or Facebook\n as email Simulate a local email identity\n\nOptions:\n --client-id <id> OAuth client/app ID (Apple Services ID)\n --client-secret <secret> OAuth client/app secret\n --client-json <path> Read provider-specific credentials JSON\n --tenant <tenant> Microsoft tenant (default: common)\n --team-id <id> Apple Developer Team ID\n --key-id <id> Apple Sign in key ID\n --private-key <pem> Apple private key (stored only in Server env)\n --graph-version <name> Facebook Graph API version\n --disable Disable the selected provider without changing siblings\n --email <address> Simulated email identity\n --display-name <name> Simulated display name\n --picture <url> Simulated profile picture URL\n --port <number> Target Dev session port\n --client <target> Delivery target: current, all, or a client ID\n --json Write JSON output\n --help, -h Show this help\n" | "Usage: sporades access-keys <command> [options]\n\nInspect and retire Access keys through a running Capsule.\n\nCommands:\n list --user-id <id> List one owner's Access-key metadata\n inspect <key-id> Inspect one Access key\n revoke <key-id> Revoke one Access key\n revoke-all --user-id <id> Revoke one owner's current Access keys\n delete <key-id> Delete revoked Access-key history\n\nOptions:\n --session <name> Session: dev, container, or hosted (default: dev)\n --host <alias> Host profile alias for a Hosted Capsule\n --subname <name> Hosted Capsule subname\n --cursor <cursor> Opaque list cursor\n --limit <n> List page size from 1 through 100\n --status <status> List active, expired, or revoked keys\n --yes Explicitly approve a destructive operation\n --json Write structured JSON; does not imply consent\n --help, -h Show this help\n" | "Usage: sporades security [options]\n\nInspect effective Capsule security policy.\n\nOptions:\n --session <name> Session: dev, public-dev, container, or hosted\n --json Write JSON output\n --help, -h Show this help\n" | "Usage: sporades doctor [options]\n\nRun read-only Sporades diagnostics.\n\nOptions:\n --session <name> Session: dev, public-dev, container, or hosted\n --host <alias> Host profile alias for Hosted Capsule checks\n --subname <name> Hosted Capsule subname\n --strict Exit non-zero on warnings as well as failures\n --json Write structured JSON output\n --help, -h Show this help\n" | "Usage: sporades env <command> [options]\n\nManage Sealed Server env.\n\nCommands:\n set <name> Read one value from stdin and seal it\n has <name> Test whether a Server env key is defined\n init Create local Sealed Server env key material\n import Import Server env values from a file\n status Print Sealed Server env status\n export Export Sealed Server env for a Host profile\n reencrypt Re-encrypt local Sealed Server env material\n\nOptions:\n --stdin Read the value for env set from stdin\n --file <path> Input file for import or export\n --host <alias> Host profile alias\n --subname <name> Hosted Capsule subname\n --output <path> Export output path\n --sealed Treat input as an already sealed export\n --json Write JSON output\n --help, -h Show this help\n" | "Usage: sporades monitoring stack <init|validate|upgrade|rollback|backup|restore> [options]\n sporades monitoring sender <issue|rotate|commit|cancel|revoke|export|status|legacy-revoke> [options]\n\nGenerate or inspect the versioned trace stack from an installed Sporades package.\nInitialization creates a reviewable directory; it does not start services.\nSender operations run locally on the Monitoring server; results contain no secrets.\nRotation stages a second generation; commit retires the old one after sender verification.\n\nOptions:\n --dir <path> Target stack directory (default: current directory)\n --backup <path> Protected cold snapshot directory (backup/restore)\n --baseline <path> Trusted prior release assets for a schema-3 upgrade\n --sender <name> Named sender for lifecycle operations (optional for status)\n --host <identity> Exact inventory Host scope (issue or legacy-revoke only)\n --out <path> New mode-0600 credential handoff file (export only)\n --generation <n> Verified pending generation to activate (commit only)\n --ingest Disable shared legacy ingestion (legacy-revoke only)\n --json Write { ok, data, error } JSON output\n --help, -h Show this help\n" | "Usage: sporades telemetry profile <add|list|show|remove> [name] [options]\n\nRegister and inspect operator-owned OTLP/HTTP Telemetry profiles. Descriptors store only\ncredential environment and private CA file references; they never store secret values.\nDev sessions use --telemetry <name> first, then sporades.json telemetry.profile, then no export.\n\nOptions for profile add:\n --endpoint <url> OTLP/HTTP base origin (HTTPS, or HTTP loopback with --loopback)\n --dashboard <url> Optional dashboard HTTPS URL\n --credential-env <KEY> Environment variable containing the ingestion bearer token\n --inventory-credential-env <KEY> Exact Host-scoped lifecycle inventory token\n --inventory-host <id> Stable inventory identity (default: first connected domain)\n --metrics-interval-ms <N> Metrics export period, 5000-300000 ms (default 15000)\n --trace-propagation-origin <origin> Approve exact fetch origin (repeatable, max 32)\n --event-loop-delay-resolution-ms <N> Delay timer precision, 10-1000 ms (default 20)\n --ca-file <path> Absolute private CA certificate path for verified TLS\n --loopback Permit a local HTTP collector for development\n --json Write { ok, data, error } JSON output\n --help, -h Show this help\n" | "Usage: sporades deploy [status|stop|restart|reconcile|remove|reset|ssh] [options]\n\nStart and manage a local Container session.\n\nCommands:\n deploy Start a local Container session\n deploy status Print Container session status\n deploy stop Stop the running Container session\n deploy restart Restart the running Container session\n deploy policy publish <file>|remove\n Publish or remove the declared admission policy\n deploy reconcile Settle an interrupted deployment-file attempt\n deploy ssh Inspect effective Container SSH access\n deploy remove Remove the Container session\n deploy reset Remove the Container session and local container state\n\nOptions:\n --port <number> Published local port when starting\n --telemetry <name> Export HTTP traces using a registered Telemetry profile\n --no-telemetry Disable export for this Container session\n --force Replace stale or conflicting container state when starting\n --json Write JSON output\n --help, -h Show this help\n" | "Usage: sporades host <command> [options]\n\nManage Host profiles and Hosted Capsules.\n\nProfile commands:\n add <alias> Add a Host profile\n use <alias> Set the default Host profile\n current Print the selected Host profile\n bootstrap Provision the remote Host server\n upgrade Copy the local Host helper to the Host server\n health [subname] Check Host server or Hosted Capsule health\n services enable|disable|uninstall|status observability [--on <alias>]\n Manage pinned GlitchTip and Umami (opt-in)\n services connect <subname> [--host <Capsule-host>] [--on <ops-host>]\n Seal configured error/analytics env; push to activate\n services backup|backups observability [--on <alias>]\n Snapshot or list service databases using Host backup policy\n services restore observability --id <snapshot> --confirm observability\n Restore disabled services; enable again after inspection\n telemetry connect|migrate|reconcile|status|check\n telemetry inventory-export|inventory-reconcile\n Manage the shared Host Telemetry relay\n telemetry exports-disable|remove-agents\n Disable exports; remove agents after inventory acknowledgement\n telemetry resources-enable|resources-disable|resources-remove\n Manage Host OS and Caddy collection independently of Capsules\n telemetry enable|disable <subname>\n Change a Hosted Capsule's Telemetry opt-out\n\nCapsule commands:\n backup configure --file <policy.json>\n Configure encrypted backups and an optional Host timer\n backup create|list|prune --subname <name>\n Manage encrypted SQLite and files snapshots\n backup restore --subname <source> --id <full-id> --confirm <destination>\n Restore a stopped Capsule; optionally --to-subname <destination>\n backup status Report last successful backup age for each Capsule\n bind <subname> Bind this project to a Hosted Capsule\n register <subname> Register a Hosted Capsule\n canonical set <subname> <alias>|clear <subname>\n Select the public origin; restart a running Capsule\n push Push and install a Hosted Capsule release\n start <subname> Start a Hosted Capsule\n stop <subname> Stop a Hosted Capsule\n restart <subname> Restart a Hosted Capsule\n policy publish <file>|remove --host <alias> --subname <name>\n Publish or remove the recorded admission policy\n reconcile <subname> Settle an interrupted deployment-file attempt\n ssh [subname] Inspect effective Hosted Capsule SSH access\n stats [subname] Print Host server or Hosted Capsule stats\n logs [source] Print Hosted Capsule logs\n releases <subname> List Hosted Capsule releases\n rollback <subname> <release-id>\n Roll back to a previous release\n rotate-key <subname>\n Rotate Hosted Capsule Sealed Server env keys\n unregister <subname>\n Unregister a Hosted Capsule\n delete <subname> Delete Hosted Capsule storage\n\nOther commands:\n list List Hosted Capsules\n github workflow write\n Write a GitHub Actions deploy workflow\n invoke <action> Invoke a low-level remote Host helper action\n\nOptions:\n --host <alias> Host profile alias\n --profile <name> Verified HTTPS Telemetry profile for connect or migrate\n --query-credential-env <name>\n Ephemeral operator user:password for check or migrate\n --server <target> SSH target for host add\n --domain <domain> Hosted domain for host add\n --canonical-domain <hostname>\n Public HTTPS link origin for register\n --alias-domain <hostname>\n Custom HTTPS domain for register (repeatable)\n --remote-root <path>\n Remote root path for host add\n --tls <mode> TLS mode: automatic or cloudflare-origin\n --subname <name> Hosted Capsule subname\n --lines <n>, -n <n> Log line count\n --allow-missing-env Push despite missing required Server env keys\n --restart Restart after host push\n --verify Verify release health after host push\n --fallback-to-previous-release\n Roll back when verified push fails\n --branch <name> GitHub workflow branch\n --file <path> GitHub workflow output path\n --dry-run Print workflow without writing it\n --force Overwrite workflow output when writing it\n --json Write JSON output\n --help, -h Show this help\n" | "Usage: sporades logs [tail] [options]\n\nPrint Dev session logs.\n\nCommands:\n logs Print recent Dev session logs\n logs tail Follow Dev session logs\n\nOptions:\n --port <number> Target Dev session or local Container port\n --json Write JSON output\n --help, -h Show this help\n" | "Usage: sporades db <command> [options]\n\nInspect the Dev session database.\n\nCommands:\n list List database tables\n dump Dump database contents\n query <sql> Run a read-only SQL query\n\nOptions:\n --port <number> Target Dev session or local Container port\n --json Write JSON output\n --help, -h Show this help\n";
|
|
49
|
+
` | "Usage: sporades dev [status|stop|reset] [options]\n\nStart and manage a local Dev session.\n\nCommands:\n dev Start a Dev session\n dev status Print Dev session status\n dev stop Stop the running Dev session\n dev reset Stop the Dev session and remove local Dev state\n\nOptions:\n --port <number> Dev session port when starting\n --public Allow non-localhost access when starting\n --telemetry <name> Export HTTP traces using a registered Telemetry profile\n --json Write JSON output\n --help, -h Show this help\n" | "Usage: sporades auth <command> [options]\n\nManage local auth configuration and identity simulation.\n\nCommands:\n status Print auth provider status\n clients List connected Dev session clients\n set <provider> Configure or disable anonymous, email, Google, Microsoft, Apple, or Facebook\n as email Simulate a local email identity\n\nOptions:\n --client-id <id> OAuth client/app ID (Apple Services ID)\n --client-secret <secret> OAuth client/app secret\n --client-json <path> Read provider-specific credentials JSON\n --tenant <tenant> Microsoft tenant (default: common)\n --team-id <id> Apple Developer Team ID\n --key-id <id> Apple Sign in key ID\n --private-key <pem> Apple private key (stored only in Server env)\n --graph-version <name> Facebook Graph API version\n --disable Disable the selected provider without changing siblings\n --email <address> Simulated email identity\n --display-name <name> Simulated display name\n --picture <url> Simulated profile picture URL\n --port <number> Target Dev session port\n --client <target> Delivery target: current, all, or a client ID\n --json Write JSON output\n --help, -h Show this help\n" | "Usage: sporades access-keys <command> [options]\n\nInspect and retire Access keys through a running Capsule.\n\nCommands:\n list --user-id <id> List one owner's Access-key metadata\n inspect <key-id> Inspect one Access key\n revoke <key-id> Revoke one Access key\n revoke-all --user-id <id> Revoke one owner's current Access keys\n delete <key-id> Delete revoked Access-key history\n\nOptions:\n --session <name> Session: dev, container, or hosted (default: dev)\n --host <alias> Host profile alias for a Hosted Capsule\n --subname <name> Hosted Capsule subname\n --cursor <cursor> Opaque list cursor\n --limit <n> List page size from 1 through 100\n --status <status> List active, expired, or revoked keys\n --yes Explicitly approve a destructive operation\n --json Write structured JSON; does not imply consent\n --help, -h Show this help\n" | "Usage: sporades security [options]\n\nInspect effective Capsule security policy.\n\nOptions:\n --session <name> Session: dev, public-dev, container, or hosted\n --json Write JSON output\n --help, -h Show this help\n" | "Usage: sporades doctor [options]\n\nRun read-only Sporades diagnostics.\n\nOptions:\n --session <name> Session: dev, public-dev, container, or hosted\n --host <alias> Host profile alias for Hosted Capsule checks\n --subname <name> Hosted Capsule subname\n --strict Exit non-zero on warnings as well as failures\n --json Write structured JSON output\n --help, -h Show this help\n" | "Usage: sporades env <command> [options]\n\nManage Sealed Server env.\n\nCommands:\n set <name> Read one value from stdin and seal it\n has <name> Test whether a Server env key is defined\n init Create local Sealed Server env key material\n import Import Server env values from a file\n status Print Sealed Server env status\n export Export Sealed Server env for a Host profile\n reencrypt Re-encrypt local Sealed Server env material\n\nOptions:\n --stdin Read the value for env set from stdin\n --file <path> Input file for import or export\n --host <alias> Host profile alias\n --subname <name> Hosted Capsule subname\n --output <path> Export output path\n --sealed Treat input as an already sealed export\n --json Write JSON output\n --help, -h Show this help\n" | "Usage: sporades monitoring stack <init|validate|upgrade|rollback|backup|restore> [options]\n sporades monitoring sender <issue|rotate|commit|cancel|revoke|export|status|legacy-revoke> [options]\n\nGenerate or inspect the versioned trace stack from an installed Sporades package.\nInitialization creates a reviewable directory; it does not start services.\nSender operations run locally on the Monitoring server; results contain no secrets.\nRotation stages a second generation; commit retires the old one after sender verification.\n\nOptions:\n --dir <path> Target stack directory (default: current directory)\n --backup <path> Protected cold snapshot directory (backup/restore)\n --baseline <path> Trusted prior release assets for a schema-3 upgrade\n --sender <name> Named sender for lifecycle operations (optional for status)\n --host <identity> Exact inventory Host scope (issue or legacy-revoke only)\n --out <path> New mode-0600 credential handoff file (export only)\n --generation <n> Verified pending generation to activate (commit only)\n --ingest Disable shared legacy ingestion (legacy-revoke only)\n --json Write { ok, data, error } JSON output\n --help, -h Show this help\n" | "Usage: sporades telemetry profile <add|list|show|remove> [name] [options]\n\nRegister and inspect operator-owned OTLP/HTTP Telemetry profiles. Descriptors store only\ncredential environment and private CA file references; they never store secret values.\nDev sessions use --telemetry <name> first, then sporades.json telemetry.profile, then no export.\n\nOptions for profile add:\n --endpoint <url> OTLP/HTTP base origin (HTTPS, or HTTP loopback with --loopback)\n --dashboard <url> Optional dashboard HTTPS URL\n --credential-env <KEY> Environment variable containing the ingestion bearer token\n --inventory-credential-env <KEY> Exact Host-scoped lifecycle inventory token\n --inventory-host <id> Stable inventory identity (default: first connected domain)\n --metrics-interval-ms <N> Metrics export period, 5000-300000 ms (default 15000)\n --trace-propagation-origin <origin> Approve exact fetch origin (repeatable, max 32)\n --event-loop-delay-resolution-ms <N> Delay timer precision, 10-1000 ms (default 20)\n --ca-file <path> Absolute private CA certificate path for verified TLS\n --loopback Permit a local HTTP collector for development\n --json Write { ok, data, error } JSON output\n --help, -h Show this help\n" | "Usage: sporades deploy [status|stop|restart|reconcile|remove|reset|ssh] [options]\n\nStart and manage a local Container session.\n\nCommands:\n deploy Start a local Container session\n deploy status Print Container session status\n deploy stop Stop the running Container session\n deploy restart Restart the running Container session\n deploy policy publish <file>|remove\n Publish or remove the declared admission policy\n deploy reconcile Settle an interrupted deployment-file attempt\n deploy ssh Inspect effective Container SSH access\n deploy remove Remove the Container session\n deploy reset Remove the Container session and local container state\n\nOptions:\n --port <number> Published local port when starting\n --telemetry <name> Export HTTP traces using a registered Telemetry profile\n --no-telemetry Disable export for this Container session\n --force Replace stale or conflicting container state when starting\n --json Write JSON output\n --help, -h Show this help\n" | "Usage: sporades host <command> [options]\n\nManage Host profiles and Hosted Capsules.\n\nProfile commands:\n add <alias> Add a Host profile\n use <alias> Set the default Host profile\n current Print the selected Host profile\n bootstrap Provision the remote Host server\n upgrade Copy the local Host helper to the Host server\n health [subname] Check Host server or Hosted Capsule health\n services enable|disable|uninstall|status observability [--on <alias>]\n Manage pinned GlitchTip and Umami (opt-in)\n services connect <subname> [--host <Capsule-host>] [--on <ops-host>]\n Seal configured error/analytics env; push to activate\n services backup|backups observability [--on <alias>]\n Snapshot or list service databases using Host backup policy\n services restore observability --id <snapshot> --confirm observability\n Restore disabled services; enable again after inspection\n telemetry connect|migrate|reconcile|status|check\n telemetry inventory-export|inventory-reconcile\n Manage the shared Host Telemetry relay\n telemetry exports-disable|remove-agents\n Disable exports; remove agents after inventory acknowledgement\n telemetry resources-enable|resources-disable|resources-remove\n Manage Host OS and Caddy collection independently of Capsules\n telemetry enable|disable <subname>\n Change a Hosted Capsule's Telemetry opt-out\n\nCapsule commands:\n backup configure --file <policy.json>\n Configure encrypted backups and an optional Host timer\n backup create|list|prune --subname <name>\n Manage encrypted SQLite and files snapshots\n backup restore --subname <source> --id <full-id> --confirm <destination>\n Restore a stopped Capsule; optionally --to-subname <destination>\n backup status Report last successful backup age for each Capsule\n bind <subname> Bind this project to a Hosted Capsule\n db list|dump|query <sql> [--subname <name>]\n Read a running Hosted Capsule's database over SSH\n register <subname> Register a Hosted Capsule\n canonical set <subname> <alias>|clear <subname>\n Select the public origin; restart a running Capsule\n push Push and install a Hosted Capsule release\n start <subname> Start a Hosted Capsule\n stop <subname> Stop a Hosted Capsule\n restart <subname> Restart a Hosted Capsule\n policy publish <file>|remove --host <alias> --subname <name>\n Publish or remove the recorded admission policy\n reconcile <subname> Settle an interrupted deployment-file attempt\n ssh [subname] Inspect effective Hosted Capsule SSH access\n stats [subname] Print Host server or Hosted Capsule stats\n logs [source] Print Hosted Capsule logs\n releases <subname> List Hosted Capsule releases\n rollback <subname> <release-id>\n Roll back to a previous release\n rotate-key <subname>\n Rotate Hosted Capsule Sealed Server env keys\n unregister <subname>\n Unregister a Hosted Capsule\n delete <subname> Delete Hosted Capsule storage\n\nOther commands:\n list List Hosted Capsules\n github workflow write\n Write a GitHub Actions deploy workflow\n invoke <action> Invoke a low-level remote Host helper action\n\nOptions:\n --host <alias> Host profile alias\n --profile <name> Verified HTTPS Telemetry profile for connect or migrate\n --query-credential-env <name>\n Ephemeral operator user:password for check or migrate\n --server <target> SSH target for host add\n --domain <domain> Hosted domain for host add\n --canonical-domain <hostname>\n Public HTTPS link origin for register\n --alias-domain <hostname>\n Custom HTTPS domain for register (repeatable)\n --remote-root <path>\n Remote root path for host add\n --tls <mode> TLS mode: automatic or cloudflare-origin\n --subname <name> Hosted Capsule subname\n --lines <n>, -n <n> Log line count\n --allow-missing-env Push despite missing required Server env keys\n --restart Restart after host push\n --verify Verify release health after host push\n --fallback-to-previous-release\n Roll back when verified push fails\n --branch <name> GitHub workflow branch\n --file <path> GitHub workflow output path\n --dry-run Print workflow without writing it\n --force Overwrite workflow output when writing it\n --json Write JSON output\n --help, -h Show this help\n" | "Usage: sporades logs [tail] [options]\n\nPrint Dev session logs.\n\nCommands:\n logs Print recent Dev session logs\n logs tail Follow Dev session logs\n\nOptions:\n --port <number> Target Dev session or local Container port\n --json Write JSON output\n --help, -h Show this help\n" | "Usage: sporades db <command> [options]\n\nInspect the Dev session database.\n\nCommands:\n list List database tables\n dump Dump database contents\n query <sql> Run a read-only SQL query\n\nOptions:\n --port <number> Target Dev session or local Container port\n --json Write JSON output\n --help, -h Show this help\n";
|
|
50
50
|
export {};
|
|
51
51
|
//# sourceMappingURL=cli-help.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli-help.d.ts","sourceRoot":"","sources":["../../src/cli/cli-help.ts"],"names":[],"mappings":"AAMA,QAAA,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"cli-help.d.ts","sourceRoot":"","sources":["../../src/cli/cli-help.ts"],"names":[],"mappings":"AAMA,QAAA,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiWL,CAAC;AAEX,MAAM,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,OAAO,SAAS,EAAE,SAAS,CAAC,CAAC;AAErE,wBAAgB,aAAa,CAAC,OAAO,CAAC,EAAE,MAAM;;;;;;;;;;;;;;;8hbAE7C"}
|
package/dist/cli/cli-help.js
CHANGED
|
@@ -246,6 +246,8 @@ Capsule commands:
|
|
|
246
246
|
Restore a stopped Capsule; optionally --to-subname <destination>
|
|
247
247
|
backup status Report last successful backup age for each Capsule
|
|
248
248
|
bind <subname> Bind this project to a Hosted Capsule
|
|
249
|
+
db list|dump|query <sql> [--subname <name>]
|
|
250
|
+
Read a running Hosted Capsule's database over SSH
|
|
249
251
|
register <subname> Register a Hosted Capsule
|
|
250
252
|
canonical set <subname> <alias>|clear <subname>
|
|
251
253
|
Select the public origin; restart a running Capsule
|
package/dist/cli/cli-help.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli-help.js","sourceRoot":"","sources":["../../src/cli/cli-help.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAEnG,MAAM,aAAa,GAAG,CAAC,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,KAAK,SAAS,CAAC,EAAE,SAAS,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC;AACnJ,MAAM,aAAa,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AACnH,MAAM,YAAY,GAAG,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC;AAElF,MAAM,SAAS,GAAG;IAChB,aAAa,EAAE;;;;;;;;;;;;;CAahB;IACC,MAAM,EAAE;;;;;;;;0CAQgC,aAAa;0CACb,aAAa;kCACrB,YAAY;;;;;CAK7C;IACC,GAAG,EAAE;;;;;;;;;;;;;;;;CAgBN;IACC,IAAI,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2BP;IACC,aAAa,EAAE;;;;;;;;;;;;;;;;;;;;;CAqBhB;IACC,QAAQ,EAAE;;;;;;;;CAQX;IACC,MAAM,EAAE;;;;;;;;;;;CAWT;IACC,GAAG,EAAE;;;;;;;;;;;;;;;;;;;;;;CAsBN;IACC,UAAU,EAAE;;;;;;;;;;;;;;;;;;;CAmBb;IACC,SAAS,EAAE;;;;;;;;;;;;;;;;;;;CAmBZ;IACC,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;;CAuBT;IACC,IAAI,EAAE
|
|
1
|
+
{"version":3,"file":"cli-help.js","sourceRoot":"","sources":["../../src/cli/cli-help.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAEnG,MAAM,aAAa,GAAG,CAAC,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,KAAK,SAAS,CAAC,EAAE,SAAS,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC;AACnJ,MAAM,aAAa,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AACnH,MAAM,YAAY,GAAG,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC;AAElF,MAAM,SAAS,GAAG;IAChB,aAAa,EAAE;;;;;;;;;;;;;CAahB;IACC,MAAM,EAAE;;;;;;;;0CAQgC,aAAa;0CACb,aAAa;kCACrB,YAAY;;;;;CAK7C;IACC,GAAG,EAAE;;;;;;;;;;;;;;;;CAgBN;IACC,IAAI,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2BP;IACC,aAAa,EAAE;;;;;;;;;;;;;;;;;;;;;CAqBhB;IACC,QAAQ,EAAE;;;;;;;;CAQX;IACC,MAAM,EAAE;;;;;;;;;;;CAWT;IACC,GAAG,EAAE;;;;;;;;;;;;;;;;;;;;;;CAsBN;IACC,UAAU,EAAE;;;;;;;;;;;;;;;;;;;CAmBb;IACC,SAAS,EAAE;;;;;;;;;;;;;;;;;;;CAmBZ;IACC,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;;CAuBT;IACC,IAAI,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+FP;IACC,IAAI,EAAE;;;;;;;;;;;;CAYP;IACC,EAAE,EAAE;;;;;;;;;;;;;CAaL;IACC,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;KAuBN;CACK,CAAC;AAIX,MAAM,UAAU,aAAa,CAAC,OAAgB;IAC5C,OAAO,SAAS,CAAC,OAAyB,CAAC,IAAI,SAAS,CAAC,OAAO,CAAC;AACnE,CAAC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const CLI_VERSION = "0.9.
|
|
1
|
+
export declare const CLI_VERSION = "0.9.40";
|
|
2
2
|
//# sourceMappingURL=cli-version.d.ts.map
|
package/dist/cli/cli-version.js
CHANGED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
type LooseRecord = Record<string, any>;
|
|
2
|
+
export declare const DATABASE_INSPECTION_ACTIONS: readonly ["db.list", "db.dump", "db.query"];
|
|
3
|
+
export type DatabaseInspectionAction = (typeof DATABASE_INSPECTION_ACTIONS)[number];
|
|
4
|
+
export declare function encodeDatabaseInspectionInput(sql: string): string | null;
|
|
5
|
+
export declare const DATABASE_INSPECTION_MAX_BUFFER: number;
|
|
6
|
+
export declare function isDatabaseInspectionAction(action: unknown): action is DatabaseInspectionAction;
|
|
7
|
+
export declare function sanitizeDatabaseInspectionEnvelope(action: DatabaseInspectionAction, envelope: LooseRecord, invalid: () => never): LooseRecord;
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=database-inspection-envelope.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database-inspection-envelope.d.ts","sourceRoot":"","sources":["../../src/cli/database-inspection-envelope.ts"],"names":[],"mappings":"AAIA,KAAK,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAEvC,eAAO,MAAM,2BAA2B,6CAA8C,CAAC;AACvF,MAAM,MAAM,wBAAwB,GAAG,CAAC,OAAO,2BAA2B,CAAC,CAAC,MAAM,CAAC,CAAC;AAOpF,wBAAgB,6BAA6B,CAAC,GAAG,EAAE,MAAM,iBAGxD;AAID,eAAO,MAAM,8BAA8B,QAAoB,CAAC;AAEhE,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,IAAI,wBAAwB,CAE9F;AAED,wBAAgB,kCAAkC,CAAC,MAAM,EAAE,wBAAwB,EAAE,QAAQ,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,KAAK,GAAG,WAAW,CAqB7I"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export const DATABASE_INSPECTION_ACTIONS = ["db.list", "db.dump", "db.query"];
|
|
2
|
+
// The Bundle refuses `--sporades-action-input` over 24 KiB of base64url, so SQL whose encoded
|
|
3
|
+
// input is larger could not reach the read-only gate in one piece. Measuring the encoded form, not
|
|
4
|
+
// the raw SQL, keeps heavily escaped SQL from passing here and failing as malformed input there.
|
|
5
|
+
const DATABASE_INSPECTION_INPUT_BYTE_LIMIT = 24 * 1024;
|
|
6
|
+
export function encodeDatabaseInspectionInput(sql) {
|
|
7
|
+
const encoded = Buffer.from(JSON.stringify({ sql }), "utf8").toString("base64url");
|
|
8
|
+
return encoded.length <= DATABASE_INSPECTION_INPUT_BYTE_LIMIT ? encoded : null;
|
|
9
|
+
}
|
|
10
|
+
// A dump answers with every inspectable row, so its frame is bounded by the Capsule's data rather
|
|
11
|
+
// than by Sporades. This is the ceiling on what one SSH or `docker exec` hop will buffer.
|
|
12
|
+
export const DATABASE_INSPECTION_MAX_BUFFER = 128 * 1024 * 1024;
|
|
13
|
+
export function isDatabaseInspectionAction(action) {
|
|
14
|
+
return DATABASE_INSPECTION_ACTIONS.includes(action);
|
|
15
|
+
}
|
|
16
|
+
export function sanitizeDatabaseInspectionEnvelope(action, envelope, invalid) {
|
|
17
|
+
const data = envelope?.data;
|
|
18
|
+
if (envelope?.ok === true && data && typeof data === "object" && !Array.isArray(data)) {
|
|
19
|
+
if (action === "db.query" && Array.isArray(data.columns) && Array.isArray(data.rows)) {
|
|
20
|
+
return { ok: true, data: { columns: data.columns, rows: data.rows }, error: null };
|
|
21
|
+
}
|
|
22
|
+
if (action !== "db.query" && Array.isArray(data.tables)) {
|
|
23
|
+
return { ok: true, data: { tables: data.tables }, error: null };
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
if (envelope?.ok === false && typeof envelope.error?.message === "string") {
|
|
27
|
+
return {
|
|
28
|
+
ok: false,
|
|
29
|
+
data: null,
|
|
30
|
+
error: {
|
|
31
|
+
message: envelope.error.message,
|
|
32
|
+
hint: typeof envelope.error.hint === "string" ? envelope.error.hint : "Check the SQL and retry the command.",
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
return invalid();
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=database-inspection-envelope.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database-inspection-envelope.js","sourceRoot":"","sources":["../../src/cli/database-inspection-envelope.ts"],"names":[],"mappings":"AAMA,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,SAAS,EAAE,SAAS,EAAE,UAAU,CAAU,CAAC;AAGvF,8FAA8F;AAC9F,mGAAmG;AACnG,iGAAiG;AACjG,MAAM,oCAAoC,GAAG,EAAE,GAAG,IAAI,CAAC;AAEvD,MAAM,UAAU,6BAA6B,CAAC,GAAW;IACvD,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;IACnF,OAAO,OAAO,CAAC,MAAM,IAAI,oCAAoC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;AACjF,CAAC;AAED,kGAAkG;AAClG,0FAA0F;AAC1F,MAAM,CAAC,MAAM,8BAA8B,GAAG,GAAG,GAAG,IAAI,GAAG,IAAI,CAAC;AAEhE,MAAM,UAAU,0BAA0B,CAAC,MAAe;IACxD,OAAQ,2BAAkD,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;AAC9E,CAAC;AAED,MAAM,UAAU,kCAAkC,CAAC,MAAgC,EAAE,QAAqB,EAAE,OAAoB;IAC9H,MAAM,IAAI,GAAG,QAAQ,EAAE,IAAI,CAAC;IAC5B,IAAI,QAAQ,EAAE,EAAE,KAAK,IAAI,IAAI,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QACtF,IAAI,MAAM,KAAK,UAAU,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YACrF,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;QACrF,CAAC;QACD,IAAI,MAAM,KAAK,UAAU,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YACxD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;QAClE,CAAC;IACH,CAAC;IACD,IAAI,QAAQ,EAAE,EAAE,KAAK,KAAK,IAAI,OAAO,QAAQ,CAAC,KAAK,EAAE,OAAO,KAAK,QAAQ,EAAE,CAAC;QAC1E,OAAO;YACL,EAAE,EAAE,KAAK;YACT,IAAI,EAAE,IAAI;YACV,KAAK,EAAE;gBACL,OAAO,EAAE,QAAQ,CAAC,KAAK,CAAC,OAAO;gBAC/B,IAAI,EAAE,OAAO,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,sCAAsC;aAC7G;SACF,CAAC;IACJ,CAAC;IACD,OAAO,OAAO,EAAE,CAAC;AACnB,CAAC"}
|