@pithy-sh/core 0.7.0 → 0.7.1
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/dist/controlPlane/capability.d.ts.map +1 -1
- package/dist/controlPlane/capability.js +5 -1
- package/dist/controlPlane/data/connection.d.ts +1 -0
- package/dist/controlPlane/data/connection.d.ts.map +1 -1
- package/dist/controlPlane/data/connection.js +1 -0
- package/dist/controlPlane/migrations/0002_management_origin.d.ts +23 -0
- package/dist/controlPlane/migrations/0002_management_origin.d.ts.map +1 -0
- package/dist/controlPlane/migrations/0002_management_origin.js +31 -0
- package/dist/version.generated.d.ts +1 -1
- package/dist/version.generated.js +1 -1
- package/package.json +1 -1
- package/src/controlPlane/capability.ts +2 -0
- package/src/controlPlane/data/connection.ts +7 -0
- package/src/controlPlane/migrations/0002_management_origin.ts +36 -0
- package/src/version.generated.ts +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"capability.d.ts","sourceRoot":"","sources":["../../src/controlPlane/capability.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,UAAU,EAAuC,MAAM,0BAA0B,CAAC;AAChG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,KAAK,EAAE,kBAAkB,EAAc,MAAM,kBAAkB,CAAC;AAGvE,OAAO,EAAE,kBAAkB,EAAE,KAAK,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"capability.d.ts","sourceRoot":"","sources":["../../src/controlPlane/capability.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,UAAU,EAAuC,MAAM,0BAA0B,CAAC;AAChG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,KAAK,EAAE,kBAAkB,EAAc,MAAM,kBAAkB,CAAC;AAGvE,OAAO,EAAE,kBAAkB,EAAE,KAAK,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAWnF,OAAO,EACL,wBAAwB,EAIzB,MAAM,kBAAkB,CAAC;AAE1B;;;;;;;;;GASG;AACH,eAAO,MAAM,4BAA4B,OAAO,CAAC;AAEjD,MAAM,MAAM,mBAAmB,GAAG,uBAAuB,CAAC;AAE1D,uEAAuE;AACvE,MAAM,WAAW,sBAAuB,SAAQ,UAAU,CAAC,eAAe,EAAE,kBAAkB,EAAE,cAAc,CAAC;IAC7G,gCAAgC;IAChC,kBAAkB,EAAE,kBAAkB,CAAC;CACxC;AAED,qGAAqG;AACrG,wBAAgB,wBAAwB,CAAC,UAAU,EAAE,UAAU,GAAG,UAAU,IAAI,sBAAsB,CAErG;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,YAAY,CAAC,OAAO,GAAE,mBAAwB,GAAG,sBAAsB,CAyJtF;AAED,4GAA4G;AAC5G,OAAO,EAAE,wBAAwB,EAAE,CAAC"}
|
|
@@ -10,6 +10,7 @@ import { capabilityHealthSources } from "./discovery/health.js";
|
|
|
10
10
|
import { createControlPlaneVerifier } from "./http/guard.js";
|
|
11
11
|
import { controlPlaneRouteDescriptors, registerControlPlaneRoutes } from "./http/routes.js";
|
|
12
12
|
import { controlplane_0001_init } from "./migrations/0001_init.js";
|
|
13
|
+
import { controlplane_0002_management_origin } from "./migrations/0002_management_origin.js";
|
|
13
14
|
import { d1ReplayGuard } from "./replay/d1Guard.js";
|
|
14
15
|
import { CONTROL_PLANE_KV_BINDING, controlPlaneKvNamespaces, kvReplayGuard } from "./replay/kvGuard.js";
|
|
15
16
|
//#region src/controlPlane/capability.ts
|
|
@@ -49,7 +50,10 @@ function isControlPlaneCapability(capability) {
|
|
|
49
50
|
*/
|
|
50
51
|
function controlplane(options = {}) {
|
|
51
52
|
const config = ControlPlaneConfig.parse(options);
|
|
52
|
-
const migrations = {
|
|
53
|
+
const migrations = {
|
|
54
|
+
"0001_init": controlplane_0001_init,
|
|
55
|
+
"0002_management_origin": controlplane_0002_management_origin
|
|
56
|
+
};
|
|
53
57
|
const requiredBindings = [{
|
|
54
58
|
type: "d1",
|
|
55
59
|
name: "DB"
|
|
@@ -51,6 +51,7 @@ export declare const ControlPlaneConnection: z.ZodObject<{
|
|
|
51
51
|
issuer: z.ZodURL;
|
|
52
52
|
workerUrl: z.ZodURL;
|
|
53
53
|
basePath: z.ZodDefault<z.ZodString>;
|
|
54
|
+
managementOrigin: z.ZodDefault<z.ZodNullable<z.ZodURL>>;
|
|
54
55
|
scopes: z.ZodCodec<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>, z.ZodArray<z.ZodString>>;
|
|
55
56
|
keys: z.ZodCodec<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodObject<{
|
|
56
57
|
keyId: z.ZodString;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../../src/controlPlane/data/connection.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB;;;;;;;;;GASG;AAEH,+EAA+E;AAC/E,eAAO,MAAM,gBAAgB;;;;iBAgBoF,CAAC;AAClH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAEjE;;;;;;GAMG;AACH,eAAO,MAAM,aAAa;;;;;;;;;;iBAoBoF,CAAC;AAC/G,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,aAAa,CAAC,CAAC;AAE3D;;;;;;;GAOG;AACH,eAAO,MAAM,sBAAsB
|
|
1
|
+
{"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../../src/controlPlane/data/connection.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB;;;;;;;;;GASG;AAEH,+EAA+E;AAC/E,eAAO,MAAM,gBAAgB;;;;iBAgBoF,CAAC;AAClH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAEjE;;;;;;GAMG;AACH,eAAO,MAAM,aAAa;;;;;;;;;;iBAoBoF,CAAC;AAC/G,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,aAAa,CAAC,CAAC;AAE3D;;;;;;;GAOG;AACH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAmDhC,CAAC;AACJ,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAC7E,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC"}
|
|
@@ -48,6 +48,7 @@ const ControlPlaneConnection = z.object({
|
|
|
48
48
|
issuer: z.url().describe("The exact `iss` this connection accepts. Verified on every call, and effectively permanent — changing the management client's origin is a migration across every registered connection, not a DNS change."),
|
|
49
49
|
workerUrl: z.url().describe("This environment's deployed Worker URL, captured at connect. The address the management client calls; re-pointed by `pithy dashboard connect --update` when a custom domain or a rename moves it."),
|
|
50
50
|
basePath: z.string().min(1).default("/control-plane").describe("Where this Worker mounts the control-plane seam, captured at connect from its resolved config. Stored beside `workerUrl` because the two together fully determine the manifest address — and this is the one part of it a client cannot discover, since it *is* the manifest's own address. Defaulted rather than required so a connection registered before the column existed still parses, reading as the default it was necessarily using."),
|
|
51
|
+
managementOrigin: z.url().nullable().default(null).describe("Where the management client that registered this connection answers — the origin the CLI calls for a verify, a rotation or a disconnect. Stored because it is not derivable: `issuer` is what that client *signs as*, and nothing says a dashboard's API answers at its own `iss`. Null for a connection registered before this column, which reads as the issuer rather than as the hosted dashboard — an older row is still a row about somebody's own deployment. Nothing on the Worker's side reads it; verification cares about `issuer` alone."),
|
|
51
52
|
scopes: sqliteJson(z.array(ControlPlaneScope)).describe("The operations this connection was granted, stored and enforced on the adopter's side. Enforced only by the caller, a scope would not be a limit at all."),
|
|
52
53
|
keys: sqliteJson(z.array(RegisteredKey)).describe("Every key this connection may sign with, current and superseded. One JSON column rather than a child table, so a rotation is one atomic UPDATE and verification is one read."),
|
|
53
54
|
createdAt: SQLiteDate.describe("When the connection was registered. Ms-epoch in SQLite, a Date in TypeScript."),
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2026 Pithy
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
import type { Migration } from "kysely/migration";
|
|
4
|
+
/**
|
|
5
|
+
* Where the management client that registered a connection answers — `#614`.
|
|
6
|
+
*
|
|
7
|
+
* **Appended, not folded into `0001`.** The seam has shipped and adopters' databases hold rows written
|
|
8
|
+
* by it; a column added to the initial migration is history rewritten under a ledger that already
|
|
9
|
+
* records `0001_init` as applied. So this is a second migration, and `0001` stays what it was.
|
|
10
|
+
*
|
|
11
|
+
* **Nullable, with no default.** Every other address on the row has an obvious value when it is absent
|
|
12
|
+
* — a seam is mounted somewhere, so `basePath` defaults. An origin does not: a row written before this
|
|
13
|
+
* column knows only what its dashboard *signs* as, and defaulting it to the hosted origin would assert
|
|
14
|
+
* that every existing self-hosted connection belongs to `app.pithy.sh`. That is the assertion that
|
|
15
|
+
* caused #614 in the first place. Null means "not recorded", the CLI falls back to the issuer, and the
|
|
16
|
+
* next `connect` writes the real answer.
|
|
17
|
+
*
|
|
18
|
+
* **The Worker never reads it.** Verification matches a token's `iss` against `issuer`; this column
|
|
19
|
+
* exists for the operator's side, so that `status --verify`, `rotate` and `disconnect` call the
|
|
20
|
+
* dashboard the connection was registered against rather than whichever one a flag's default names.
|
|
21
|
+
*/
|
|
22
|
+
export declare const controlplane_0002_management_origin: Migration;
|
|
23
|
+
//# sourceMappingURL=0002_management_origin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"0002_management_origin.d.ts","sourceRoot":"","sources":["../../../src/controlPlane/migrations/0002_management_origin.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAElD;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,mCAAmC,EAAE,SAWjD,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2026 Pithy
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
//#region src/controlPlane/migrations/0002_management_origin.ts
|
|
4
|
+
/**
|
|
5
|
+
* Where the management client that registered a connection answers — `#614`.
|
|
6
|
+
*
|
|
7
|
+
* **Appended, not folded into `0001`.** The seam has shipped and adopters' databases hold rows written
|
|
8
|
+
* by it; a column added to the initial migration is history rewritten under a ledger that already
|
|
9
|
+
* records `0001_init` as applied. So this is a second migration, and `0001` stays what it was.
|
|
10
|
+
*
|
|
11
|
+
* **Nullable, with no default.** Every other address on the row has an obvious value when it is absent
|
|
12
|
+
* — a seam is mounted somewhere, so `basePath` defaults. An origin does not: a row written before this
|
|
13
|
+
* column knows only what its dashboard *signs* as, and defaulting it to the hosted origin would assert
|
|
14
|
+
* that every existing self-hosted connection belongs to `app.pithy.sh`. That is the assertion that
|
|
15
|
+
* caused #614 in the first place. Null means "not recorded", the CLI falls back to the issuer, and the
|
|
16
|
+
* next `connect` writes the real answer.
|
|
17
|
+
*
|
|
18
|
+
* **The Worker never reads it.** Verification matches a token's `iss` against `issuer`; this column
|
|
19
|
+
* exists for the operator's side, so that `status --verify`, `rotate` and `disconnect` call the
|
|
20
|
+
* dashboard the connection was registered against rather than whichever one a flag's default names.
|
|
21
|
+
*/
|
|
22
|
+
const controlplane_0002_management_origin = {
|
|
23
|
+
up: async (db) => {
|
|
24
|
+
await db.schema.alterTable("pithyControlplaneConnections").addColumn("managementOrigin", "text").execute();
|
|
25
|
+
},
|
|
26
|
+
down: async (db) => {
|
|
27
|
+
await db.schema.alterTable("pithyControlplaneConnections").dropColumn("managementOrigin").execute();
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
//#endregion
|
|
31
|
+
export { controlplane_0002_management_origin };
|
|
@@ -3,5 +3,5 @@
|
|
|
3
3
|
/** This package's npm name — the join key against a release feed. */
|
|
4
4
|
export declare const PACKAGE_NAME = "@pithy-sh/core";
|
|
5
5
|
/** This package's version, stamped from its own package.json at generation time. */
|
|
6
|
-
export declare const PACKAGE_VERSION = "0.7.
|
|
6
|
+
export declare const PACKAGE_VERSION = "0.7.1";
|
|
7
7
|
//# sourceMappingURL=version.generated.d.ts.map
|
|
@@ -4,6 +4,6 @@
|
|
|
4
4
|
/** This package's npm name — the join key against a release feed. */
|
|
5
5
|
const PACKAGE_NAME = "@pithy-sh/core";
|
|
6
6
|
/** This package's version, stamped from its own package.json at generation time. */
|
|
7
|
-
const PACKAGE_VERSION = "0.7.
|
|
7
|
+
const PACKAGE_VERSION = "0.7.1";
|
|
8
8
|
//#endregion
|
|
9
9
|
export { PACKAGE_NAME, PACKAGE_VERSION };
|
package/package.json
CHANGED
|
@@ -17,6 +17,7 @@ import { type CapabilityHealthSource, capabilityHealthSources } from "./discover
|
|
|
17
17
|
import { createControlPlaneVerifier } from "./http/guard";
|
|
18
18
|
import { controlPlaneRouteDescriptors, registerControlPlaneRoutes } from "./http/routes";
|
|
19
19
|
import { controlplane_0001_init } from "./migrations/0001_init";
|
|
20
|
+
import { controlplane_0002_management_origin } from "./migrations/0002_management_origin";
|
|
20
21
|
import { d1ReplayGuard } from "./replay/d1Guard";
|
|
21
22
|
import type { ReplayGuard } from "./replay/guard";
|
|
22
23
|
import {
|
|
@@ -77,6 +78,7 @@ export function controlplane(options: ControlPlaneOptions = {}): ControlPlaneCap
|
|
|
77
78
|
|
|
78
79
|
const migrations: Record<string, Migration> = {
|
|
79
80
|
"0001_init": controlplane_0001_init,
|
|
81
|
+
"0002_management_origin": controlplane_0002_management_origin,
|
|
80
82
|
};
|
|
81
83
|
const requiredBindings: BindingSpecInput[] = [
|
|
82
84
|
// The app database — the connections table lives here, beside auth's and audit's. Not the secrets
|
|
@@ -105,6 +105,13 @@ export const ControlPlaneConnection = z
|
|
|
105
105
|
.describe(
|
|
106
106
|
"Where this Worker mounts the control-plane seam, captured at connect from its resolved config. Stored beside `workerUrl` because the two together fully determine the manifest address — and this is the one part of it a client cannot discover, since it *is* the manifest's own address. Defaulted rather than required so a connection registered before the column existed still parses, reading as the default it was necessarily using.",
|
|
107
107
|
),
|
|
108
|
+
managementOrigin: z
|
|
109
|
+
.url()
|
|
110
|
+
.nullable()
|
|
111
|
+
.default(null)
|
|
112
|
+
.describe(
|
|
113
|
+
"Where the management client that registered this connection answers — the origin the CLI calls for a verify, a rotation or a disconnect. Stored because it is not derivable: `issuer` is what that client *signs as*, and nothing says a dashboard's API answers at its own `iss`. Null for a connection registered before this column, which reads as the issuer rather than as the hosted dashboard — an older row is still a row about somebody's own deployment. Nothing on the Worker's side reads it; verification cares about `issuer` alone.",
|
|
114
|
+
),
|
|
108
115
|
scopes: sqliteJson(z.array(ControlPlaneScope)).describe(
|
|
109
116
|
"The operations this connection was granted, stored and enforced on the adopter's side. Enforced only by the caller, a scope would not be a limit at all.",
|
|
110
117
|
),
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2026 Pithy
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
import type { Kysely } from "kysely";
|
|
5
|
+
import type { Migration } from "kysely/migration";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Where the management client that registered a connection answers — `#614`.
|
|
9
|
+
*
|
|
10
|
+
* **Appended, not folded into `0001`.** The seam has shipped and adopters' databases hold rows written
|
|
11
|
+
* by it; a column added to the initial migration is history rewritten under a ledger that already
|
|
12
|
+
* records `0001_init` as applied. So this is a second migration, and `0001` stays what it was.
|
|
13
|
+
*
|
|
14
|
+
* **Nullable, with no default.** Every other address on the row has an obvious value when it is absent
|
|
15
|
+
* — a seam is mounted somewhere, so `basePath` defaults. An origin does not: a row written before this
|
|
16
|
+
* column knows only what its dashboard *signs* as, and defaulting it to the hosted origin would assert
|
|
17
|
+
* that every existing self-hosted connection belongs to `app.pithy.sh`. That is the assertion that
|
|
18
|
+
* caused #614 in the first place. Null means "not recorded", the CLI falls back to the issuer, and the
|
|
19
|
+
* next `connect` writes the real answer.
|
|
20
|
+
*
|
|
21
|
+
* **The Worker never reads it.** Verification matches a token's `iss` against `issuer`; this column
|
|
22
|
+
* exists for the operator's side, so that `status --verify`, `rotate` and `disconnect` call the
|
|
23
|
+
* dashboard the connection was registered against rather than whichever one a flag's default names.
|
|
24
|
+
*/
|
|
25
|
+
export const controlplane_0002_management_origin: Migration = {
|
|
26
|
+
up: async (db: Kysely<unknown>): Promise<void> => {
|
|
27
|
+
await db.schema.alterTable("pithyControlplaneConnections").addColumn("managementOrigin", "text").execute();
|
|
28
|
+
},
|
|
29
|
+
|
|
30
|
+
down: async (db: Kysely<unknown>): Promise<void> => {
|
|
31
|
+
// SQLite has dropped columns since 3.35 and D1 carries a newer engine, so the twelve-step rebuild is
|
|
32
|
+
// not needed here — and a rebuild would be the riskier `down`, since it rewrites every row of a table
|
|
33
|
+
// holding live credentials to remove a column nothing reads.
|
|
34
|
+
await db.schema.alterTable("pithyControlplaneConnections").dropColumn("managementOrigin").execute();
|
|
35
|
+
},
|
|
36
|
+
};
|
package/src/version.generated.ts
CHANGED