@wtfalch/foundry 0.16.15 → 0.17.0
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/apply.d.ts +22 -1
- package/dist/bootstrap/bootstrap.d.ts +6 -1
- package/dist/bootstrap/bootstrap.js +26 -3
- package/dist/bootstrap/declare.d.ts +11 -1
- package/dist/bootstrap/declare.js +12 -2
- package/dist/index.d.ts +9 -4
- package/dist/index.js +7 -0
- package/dist/migrations/0038_calls_version_pin.sql +8 -0
- package/dist/migrations/0039_destroy_record.sql +7 -0
- package/dist/migrations/0040_company_included_uuid.sql +72 -0
- package/dist/migrations/0041_company_included_uuid_keys.sql +132 -0
- package/dist/migrations/0042_mutation_leases.sql +12 -0
- package/dist/org.d.ts +82 -5
- package/dist/org.js +62 -1
- package/dist/plan/adopt.d.ts +76 -0
- package/dist/plan/adopt.js +184 -0
- package/dist/plan/agora.d.ts +21 -0
- package/dist/plan/agora.js +37 -0
- package/dist/plan/broker-entries.d.ts +9 -1
- package/dist/plan/broker-entries.js +13 -5
- package/dist/plan/chat-matrix.d.ts +1 -1
- package/dist/plan/chat-matrix.js +11 -3
- package/dist/plan/core-files.d.ts +25 -0
- package/dist/plan/core-files.js +25 -0
- package/dist/plan/deploy-health.d.ts +136 -0
- package/dist/plan/deploy-health.js +153 -0
- package/dist/plan/diff.d.ts +11 -3
- package/dist/plan/diff.js +77 -71
- package/dist/plan/entry-ai-key.d.ts +3 -3
- package/dist/plan/entry-files-key.d.ts +6 -4
- package/dist/plan/entry-files-key.js +7 -10
- package/dist/plan/executor.d.ts +109 -28
- package/dist/plan/executor.js +213 -56
- package/dist/plan/hostnames.d.ts +6 -0
- package/dist/plan/hostnames.js +13 -0
- package/dist/plan/index.d.ts +5 -1
- package/dist/plan/index.js +3 -1
- package/dist/plan/live.d.ts +5 -0
- package/dist/plan/login-host.d.ts +1 -1
- package/dist/plan/login-host.js +6 -5
- package/dist/plan/plan-apply.d.ts +153 -3
- package/dist/plan/plan-apply.js +584 -69
- package/dist/plan/platform-diff.d.ts +103 -9
- package/dist/plan/platform-diff.js +192 -14
- package/dist/plan/platform-org.d.ts +25 -0
- package/dist/plan/platform-org.js +17 -1
- package/dist/plan/platform-providers.d.ts +38 -5
- package/dist/plan/platform-providers.js +592 -109
- package/dist/plan/providers-readers.d.ts +2 -0
- package/dist/plan/providers-readers.js +4 -0
- package/dist/plan/rollout.d.ts +52 -0
- package/dist/plan/rollout.js +37 -0
- package/dist/plan/step-system.d.ts +22 -0
- package/dist/plan/step-system.js +37 -0
- package/dist/plan.d.ts +3 -0
- package/dist/state.d.ts +13 -0
- package/dist/store/audit.js +15 -1
- package/dist/store/postgres.d.ts +1 -1
- package/dist/store/postgres.js +127 -14
- package/dist/store/schema.d.ts +134 -5
- package/dist/store/schema.js +12 -1
- package/dist/store.d.ts +47 -4
- package/dist/store.js +9 -1
- package/package.json +2 -2
package/dist/store/schema.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { bigserial, boolean, integer, jsonb, pgTable, text, timestamp } from 'drizzle-orm/pg-core';
|
|
1
|
+
import { bigint, bigserial, boolean, integer, jsonb, pgTable, text, timestamp, } from 'drizzle-orm/pg-core';
|
|
2
2
|
/**
|
|
3
3
|
* Mirrors `migrations/0001_declared_org.sql`, which is the source of truth:
|
|
4
4
|
* the SQL carries the CHECKs drizzle-kit does not generate here (this
|
|
@@ -31,6 +31,9 @@ export const declaredOrgs = pgTable('foundry_declared_orgs', {
|
|
|
31
31
|
chatUsesDomain: boolean('chat_uses_domain').notNull().default(false),
|
|
32
32
|
callsEnabled: boolean('calls_enabled').notNull().default(false),
|
|
33
33
|
callsUsesDomain: boolean('calls_uses_domain').notNull().default(false),
|
|
34
|
+
// #259: null holds no pin -- the stack follows versions.json, same as today.
|
|
35
|
+
callsVersionPinSynapse: text('calls_version_pin_synapse'),
|
|
36
|
+
callsVersionPinMas: text('calls_version_pin_mas'),
|
|
34
37
|
issuerUsesDomain: boolean('issuer_uses_domain').notNull().default(false),
|
|
35
38
|
// SiteConfig (org.ts, T10). A brand new org has no cms site.
|
|
36
39
|
siteEnabled: boolean('site_enabled').notNull().default(false),
|
|
@@ -101,6 +104,14 @@ export const foundryAppliedState = pgTable('foundry_applied_state', {
|
|
|
101
104
|
failedFields: jsonb('failed_fields').notNull().default([]).$type(),
|
|
102
105
|
lastAppliedAt: timestamp('last_applied_at', { withTimezone: true }),
|
|
103
106
|
lastAppliedDeclaredOrgVersion: text('last_applied_declared_org_version'),
|
|
107
|
+
destroy: jsonb('destroy').$type(),
|
|
108
|
+
});
|
|
109
|
+
/** Mirrors `migrations/0042_mutation_leases.sql`: one row per lock scope; `token` only ever rises (#441). */
|
|
110
|
+
export const foundryMutationLeases = pgTable('foundry_mutation_leases', {
|
|
111
|
+
scope: text('scope').primaryKey(),
|
|
112
|
+
token: bigint('token', { mode: 'number' }).notNull(),
|
|
113
|
+
holder: text('holder').notNull(),
|
|
114
|
+
expiresAt: timestamp('expires_at', { withTimezone: true }).notNull(),
|
|
104
115
|
});
|
|
105
116
|
/**
|
|
106
117
|
* Mirrors `migrations/0036_applied_versions.sql`, the source of truth: an
|
package/dist/store.d.ts
CHANGED
|
@@ -13,6 +13,24 @@ export interface StaleUpdate {
|
|
|
13
13
|
/** The org as it stands now. */
|
|
14
14
|
current: DeclaredOrg;
|
|
15
15
|
}
|
|
16
|
+
/**
|
|
17
|
+
* A held mutation lease (#441). `token` rises on every acquire of a scope, so
|
|
18
|
+
* a worker whose lease expired and was taken over holds a token the store no
|
|
19
|
+
* longer accepts: its fenced writes are refused.
|
|
20
|
+
*/
|
|
21
|
+
export interface MutationLease {
|
|
22
|
+
scope: string;
|
|
23
|
+
token: number;
|
|
24
|
+
}
|
|
25
|
+
/** What `acquireMutationLease` returns while another holder has the scope: when that lease runs out. */
|
|
26
|
+
export interface HeldLease {
|
|
27
|
+
heldUntil: Date;
|
|
28
|
+
}
|
|
29
|
+
/** A fenced write (`putAppliedState`, `putServiceIds`) came from a lease that is no longer the current one (#441). Nothing was written. */
|
|
30
|
+
export declare class StaleLeaseError extends Error {
|
|
31
|
+
readonly scope: string;
|
|
32
|
+
constructor(scope: string);
|
|
33
|
+
}
|
|
16
34
|
/**
|
|
17
35
|
* The persistence seam https://github.com/wtfalch/foundry/issues/18
|
|
18
36
|
* implements: create, read and edit a {@link DeclaredOrg}, and read and
|
|
@@ -44,6 +62,12 @@ export interface DeclaredOrgStore {
|
|
|
44
62
|
* record instead.
|
|
45
63
|
*/
|
|
46
64
|
findOrgIdForZone(zoneId: string): Promise<OrgId | null>;
|
|
65
|
+
/**
|
|
66
|
+
* Archon#271: an org other than `exceptOrgId` whose applied state records
|
|
67
|
+
* `id` as a Coolify app, database or project, or `null`. Adopt refuses a
|
|
68
|
+
* resource another org already holds.
|
|
69
|
+
*/
|
|
70
|
+
findOtherOrgRecordingCoolifyId(id: string, exceptOrgId: OrgId): Promise<OrgId | null>;
|
|
47
71
|
/**
|
|
48
72
|
* Combinations foundry knows are impossible are rejected with a reason
|
|
49
73
|
* (#18 "Done when"), so a caller must be ready for this to throw rather
|
|
@@ -58,7 +82,26 @@ export interface DeclaredOrgStore {
|
|
|
58
82
|
*/
|
|
59
83
|
update(id: OrgId, patch: Partial<DeclaredOrg>, opts: UpdateOptions): Promise<DeclaredOrg | StaleUpdate>;
|
|
60
84
|
getAppliedState(id: OrgId): Promise<AppliedState | null>;
|
|
61
|
-
|
|
85
|
+
/**
|
|
86
|
+
* With `fence` (#441), compare-and-set: the write happens only while
|
|
87
|
+
* `fence.token` is still the scope's current lease token, otherwise it
|
|
88
|
+
* throws {@link StaleLeaseError} and writes nothing.
|
|
89
|
+
*/
|
|
90
|
+
putAppliedState(state: AppliedState, fence?: MutationLease): Promise<void>;
|
|
91
|
+
/**
|
|
92
|
+
* #441: takes the exclusive mutation lease for `scope` (`company:<orgId>`
|
|
93
|
+
* or `platform`), or returns {@link HeldLease} while another holder's lease
|
|
94
|
+
* has not expired. Every successful acquire issues a higher token than the last.
|
|
95
|
+
*/
|
|
96
|
+
acquireMutationLease(scope: string, holder: string, ttlMs: number): Promise<MutationLease | HeldLease>;
|
|
97
|
+
/**
|
|
98
|
+
* Extends the lease to `ttlMs` from now, only while `lease.token` is still
|
|
99
|
+
* the scope's current token. Returns false once it is not: the holder lost
|
|
100
|
+
* the scope and must stop before its next provider step.
|
|
101
|
+
*/
|
|
102
|
+
renewMutationLease(lease: MutationLease, ttlMs: number): Promise<boolean>;
|
|
103
|
+
/** Frees the lease at once. A no-op if the lease was already taken over. */
|
|
104
|
+
releaseMutationLease(lease: MutationLease): Promise<void>;
|
|
62
105
|
/**
|
|
63
106
|
* Removes the declared org and its applied state together. Called only by
|
|
64
107
|
* `FoundryPlanApply.destroy` (`plan/plan-apply.ts`), once every resource it
|
|
@@ -68,7 +111,7 @@ export interface DeclaredOrgStore {
|
|
|
68
111
|
* not an error, so a retried destroy that reaches this step twice never
|
|
69
112
|
* throws.
|
|
70
113
|
*/
|
|
71
|
-
delete(id: OrgId): Promise<void>;
|
|
114
|
+
delete(id: OrgId, fence?: MutationLease): Promise<void>;
|
|
72
115
|
}
|
|
73
116
|
/**
|
|
74
117
|
* The persistence seam for #166's {@link DeclaredPlatform}, mirroring
|
|
@@ -87,8 +130,8 @@ export interface PlatformStore {
|
|
|
87
130
|
* before the first apply. `put` never touches it.
|
|
88
131
|
*/
|
|
89
132
|
getServiceIds(): Promise<Record<string, string>>;
|
|
90
|
-
/** Replaces the recorded ids. A no-op until the platform is declared. */
|
|
91
|
-
putServiceIds(serviceIds: Record<string, string
|
|
133
|
+
/** Replaces the recorded ids. A no-op until the platform is declared. With `fence` (#441), compare-and-set as {@link DeclaredOrgStore.putAppliedState}. */
|
|
134
|
+
putServiceIds(serviceIds: Record<string, string>, fence?: MutationLease): Promise<void>;
|
|
92
135
|
}
|
|
93
136
|
/**
|
|
94
137
|
* One recorded apply, appended to the history #253 keeps beside
|
package/dist/store.js
CHANGED
|
@@ -1 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
/** A fenced write (`putAppliedState`, `putServiceIds`) came from a lease that is no longer the current one (#441). Nothing was written. */
|
|
2
|
+
export class StaleLeaseError extends Error {
|
|
3
|
+
scope;
|
|
4
|
+
constructor(scope) {
|
|
5
|
+
super(`mutation lease for ${scope} was lost to a newer holder; nothing written`);
|
|
6
|
+
this.scope = scope;
|
|
7
|
+
this.name = 'StaleLeaseError';
|
|
8
|
+
}
|
|
9
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wtfalch/foundry",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.17.0",
|
|
4
4
|
"description": "Foundry's SDK: the declared org's types, the plan and apply contracts, and the state store's interface.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"@wtfalch/audit": "0.6.0",
|
|
44
44
|
"@wtfalch/auth": "0.16.0",
|
|
45
45
|
"@wtfalch/email": "^0.17.0",
|
|
46
|
-
"@wtfalch/providers": "0.7.
|
|
46
|
+
"@wtfalch/providers": "0.7.3",
|
|
47
47
|
"ssh2": "1.17.0",
|
|
48
48
|
"zod": "4.6.5"
|
|
49
49
|
},
|