@rizom/ops 0.2.0-alpha.14 → 0.2.0-alpha.141
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/README.md +3 -1
- package/dist/brains-ops.js +211 -194
- package/dist/cert-bootstrap.d.ts +1 -1
- package/dist/content-repo.d.ts +1 -0
- package/dist/deploy.js +3 -170
- package/dist/entries/deploy.d.ts +2 -2
- package/dist/index.d.ts +2 -0
- package/dist/index.js +211 -194
- package/dist/load-registry.d.ts +13 -2
- package/dist/observed-status.d.ts +1 -1
- package/dist/origin-ca.d.ts +1 -1
- package/dist/parse-args.d.ts +2 -0
- package/dist/push-secrets.d.ts +2 -9
- package/dist/push-target.d.ts +1 -2
- package/dist/run-command.d.ts +1 -1
- package/dist/run-subprocess.d.ts +1 -6
- package/dist/schema.d.ts +54 -18
- package/dist/secrets-encrypt.d.ts +4 -4
- package/dist/ssh-key-bootstrap.d.ts +1 -26
- package/dist/user-add.d.ts +15 -0
- package/dist/verify-user.d.ts +19 -0
- package/package.json +6 -4
- package/templates/rover-pilot/.env.schema +17 -3
- package/templates/rover-pilot/.github/workflows/build.yml +13 -5
- package/templates/rover-pilot/.github/workflows/deploy.yml +31 -10
- package/templates/rover-pilot/.github/workflows/reconcile.yml +16 -2
- package/templates/rover-pilot/README.md +3 -1
- package/templates/rover-pilot/deploy/scripts/decrypt-user-secrets.ts +1 -5
- package/templates/rover-pilot/deploy/scripts/resolve-deploy-handles.ts +12 -3
- package/templates/rover-pilot/deploy/scripts/update-dns.ts +14 -4
- package/templates/rover-pilot/docs/onboarding-checklist.md +32 -12
- package/templates/rover-pilot/docs/operator-playbook.md +117 -6
- package/templates/rover-pilot/docs/user-onboarding.md +81 -346
- package/templates/rover-pilot/pilot.yaml +1 -1
- package/templates/rover-pilot/.kamal/hooks/pre-deploy +0 -9
- package/templates/rover-pilot/deploy/Caddyfile +0 -72
- package/templates/rover-pilot/deploy/Dockerfile +0 -38
- package/templates/rover-pilot/deploy/kamal/deploy.yml +0 -40
package/dist/load-registry.d.ts
CHANGED
|
@@ -14,7 +14,6 @@ export interface ResolvedCohort {
|
|
|
14
14
|
presetOverride?: PilotPreset;
|
|
15
15
|
aiApiKeyOverride?: string;
|
|
16
16
|
gitSyncTokenOverride?: string;
|
|
17
|
-
mcpAuthTokenOverride?: string;
|
|
18
17
|
}
|
|
19
18
|
export interface ResolvedAnchorProfileSocialLink {
|
|
20
19
|
platform: "github" | "instagram" | "linkedin" | "email" | "website";
|
|
@@ -29,6 +28,16 @@ export interface ResolvedAnchorProfile {
|
|
|
29
28
|
story?: string;
|
|
30
29
|
socialLinks?: ResolvedAnchorProfileSocialLink[];
|
|
31
30
|
}
|
|
31
|
+
export interface ResolvedSetupDelivery {
|
|
32
|
+
delivery: "email";
|
|
33
|
+
email: string;
|
|
34
|
+
}
|
|
35
|
+
export interface ResolvedAtprotoConfig {
|
|
36
|
+
identifier: string;
|
|
37
|
+
}
|
|
38
|
+
export interface ResolvedPlaybooksConfig {
|
|
39
|
+
onboarding?: boolean | undefined;
|
|
40
|
+
}
|
|
32
41
|
export interface ResolvedUserIdentity {
|
|
33
42
|
handle: string;
|
|
34
43
|
cohort: string;
|
|
@@ -41,7 +50,9 @@ export interface ResolvedUserIdentity {
|
|
|
41
50
|
discordAnchorUserId?: string;
|
|
42
51
|
effectiveAiApiKey: string;
|
|
43
52
|
effectiveGitSyncToken: string;
|
|
44
|
-
|
|
53
|
+
setup?: ResolvedSetupDelivery;
|
|
54
|
+
atproto?: ResolvedAtprotoConfig;
|
|
55
|
+
playbooks?: ResolvedPlaybooksConfig;
|
|
45
56
|
anchorProfile: ResolvedAnchorProfile;
|
|
46
57
|
snapshotStatus: SnapshotStatus;
|
|
47
58
|
}
|
package/dist/origin-ca.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { createOriginCertificateRequest, generateOriginKeyPair, issueCloudflareOriginCertificate, setCloudflareZoneSslStrict, type CloudflareOriginCaResult, type FetchLike, type OriginCertificateRequest, type OriginKeyPair, } from "@brains/
|
|
1
|
+
export { createOriginCertificateRequest, generateOriginKeyPair, issueCloudflareOriginCertificate, setCloudflareZoneSslStrict, type CloudflareOriginCaResult, type FetchLike, type OriginCertificateRequest, type OriginKeyPair, } from "@brains/deploy-support/origin-ca";
|
package/dist/parse-args.d.ts
CHANGED
|
@@ -6,6 +6,8 @@ export interface ParsedArgs {
|
|
|
6
6
|
version?: boolean | undefined;
|
|
7
7
|
dryRun?: boolean | undefined;
|
|
8
8
|
pushTo?: string | undefined;
|
|
9
|
+
cohort?: string | undefined;
|
|
10
|
+
anchorId?: string | undefined;
|
|
9
11
|
};
|
|
10
12
|
}
|
|
11
13
|
export declare function parseArgs(argv: string[]): ParsedArgs;
|
package/dist/push-secrets.d.ts
CHANGED
|
@@ -1,9 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
export type SecretPair = readonly [name: string, value: string];
|
|
4
|
-
export interface PushSecretsOptions {
|
|
5
|
-
runCommand?: RunCommand | undefined;
|
|
6
|
-
logger?: ((message: string) => void) | undefined;
|
|
7
|
-
}
|
|
8
|
-
export declare function pushSecretsToBackend(_target: PushTarget, secrets: readonly SecretPair[], options?: PushSecretsOptions): Promise<void>;
|
|
9
|
-
export { normalizePushTarget };
|
|
1
|
+
export { pushSecretsToBackend, type PushSecretsOptions, type SecretPair, } from "@brains/deploy-support/push-secrets";
|
|
2
|
+
export { normalizePushTarget } from "@brains/deploy-support/push-target";
|
package/dist/push-target.d.ts
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
export type PushTarget
|
|
2
|
-
export declare function normalizePushTarget(value?: string): PushTarget | undefined;
|
|
1
|
+
export { normalizePushTarget, type PushTarget, } from "@brains/deploy-support/push-target";
|
package/dist/run-command.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { FetchLike } from "@brains/
|
|
1
|
+
import type { FetchLike } from "@brains/deploy-support/origin-ca";
|
|
2
2
|
import type { LoadPilotRegistryOptions } from "./load-registry";
|
|
3
3
|
import { type LookupHost } from "./observed-status";
|
|
4
4
|
import type { ParsedArgs } from "./parse-args";
|
package/dist/run-subprocess.d.ts
CHANGED
|
@@ -1,6 +1 @@
|
|
|
1
|
-
export type RunCommand
|
|
2
|
-
stdin?: string;
|
|
3
|
-
env?: NodeJS.ProcessEnv;
|
|
4
|
-
cwd?: string;
|
|
5
|
-
}) => Promise<void>;
|
|
6
|
-
export declare const runSubprocess: RunCommand;
|
|
1
|
+
export { runSubprocess, type RunCommand, } from "@brains/deploy-support/run-subprocess";
|
package/dist/schema.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { z } from "@brains/utils";
|
|
1
|
+
import { z } from "@brains/utils/zod";
|
|
2
2
|
export declare const presetSchema: z.ZodEnum<["core", "default", "pro"]>;
|
|
3
3
|
export declare const exactVersionSchema: z.ZodString;
|
|
4
4
|
export declare const handleSchema: z.ZodString;
|
|
@@ -14,7 +14,7 @@ export declare const pilotSchema: z.ZodObject<{
|
|
|
14
14
|
preset: z.ZodEnum<["core", "default", "pro"]>;
|
|
15
15
|
aiApiKey: z.ZodString;
|
|
16
16
|
gitSyncToken: z.ZodString;
|
|
17
|
-
|
|
17
|
+
contentRepoAdminToken: z.ZodString;
|
|
18
18
|
agePublicKey: z.ZodString;
|
|
19
19
|
}, "strict", z.ZodTypeAny, {
|
|
20
20
|
agePublicKey: string;
|
|
@@ -27,7 +27,7 @@ export declare const pilotSchema: z.ZodObject<{
|
|
|
27
27
|
preset: "default" | "core" | "pro";
|
|
28
28
|
aiApiKey: string;
|
|
29
29
|
gitSyncToken: string;
|
|
30
|
-
|
|
30
|
+
contentRepoAdminToken: string;
|
|
31
31
|
}, {
|
|
32
32
|
agePublicKey: string;
|
|
33
33
|
schemaVersion: 1;
|
|
@@ -39,7 +39,7 @@ export declare const pilotSchema: z.ZodObject<{
|
|
|
39
39
|
preset: "default" | "core" | "pro";
|
|
40
40
|
aiApiKey: string;
|
|
41
41
|
gitSyncToken: string;
|
|
42
|
-
|
|
42
|
+
contentRepoAdminToken: string;
|
|
43
43
|
}>;
|
|
44
44
|
export declare const userSchema: z.ZodObject<{
|
|
45
45
|
handle: z.ZodString;
|
|
@@ -55,7 +55,30 @@ export declare const userSchema: z.ZodObject<{
|
|
|
55
55
|
}>;
|
|
56
56
|
aiApiKeyOverride: z.ZodOptional<z.ZodString>;
|
|
57
57
|
gitSyncTokenOverride: z.ZodOptional<z.ZodString>;
|
|
58
|
-
|
|
58
|
+
setup: z.ZodOptional<z.ZodObject<{
|
|
59
|
+
delivery: z.ZodLiteral<"email">;
|
|
60
|
+
email: z.ZodString;
|
|
61
|
+
}, "strict", z.ZodTypeAny, {
|
|
62
|
+
email: string;
|
|
63
|
+
delivery: "email";
|
|
64
|
+
}, {
|
|
65
|
+
email: string;
|
|
66
|
+
delivery: "email";
|
|
67
|
+
}>>;
|
|
68
|
+
atproto: z.ZodOptional<z.ZodObject<{
|
|
69
|
+
identifier: z.ZodString;
|
|
70
|
+
}, "strict", z.ZodTypeAny, {
|
|
71
|
+
identifier: string;
|
|
72
|
+
}, {
|
|
73
|
+
identifier: string;
|
|
74
|
+
}>>;
|
|
75
|
+
playbooks: z.ZodOptional<z.ZodObject<{
|
|
76
|
+
onboarding: z.ZodOptional<z.ZodBoolean>;
|
|
77
|
+
}, "strict", z.ZodTypeAny, {
|
|
78
|
+
onboarding?: boolean | undefined;
|
|
79
|
+
}, {
|
|
80
|
+
onboarding?: boolean | undefined;
|
|
81
|
+
}>>;
|
|
59
82
|
anchorProfile: z.ZodOptional<z.ZodObject<{
|
|
60
83
|
name: z.ZodOptional<z.ZodString>;
|
|
61
84
|
description: z.ZodOptional<z.ZodString>;
|
|
@@ -67,12 +90,12 @@ export declare const userSchema: z.ZodObject<{
|
|
|
67
90
|
url: z.ZodString;
|
|
68
91
|
label: z.ZodOptional<z.ZodString>;
|
|
69
92
|
}, "strict", z.ZodTypeAny, {
|
|
70
|
-
url: string;
|
|
71
93
|
platform: "github" | "instagram" | "linkedin" | "email" | "website";
|
|
94
|
+
url: string;
|
|
72
95
|
label?: string | undefined;
|
|
73
96
|
}, {
|
|
74
|
-
url: string;
|
|
75
97
|
platform: "github" | "instagram" | "linkedin" | "email" | "website";
|
|
98
|
+
url: string;
|
|
76
99
|
label?: string | undefined;
|
|
77
100
|
}>, "many">>;
|
|
78
101
|
}, "strict", z.ZodTypeAny, {
|
|
@@ -82,8 +105,8 @@ export declare const userSchema: z.ZodObject<{
|
|
|
82
105
|
description?: string | undefined;
|
|
83
106
|
story?: string | undefined;
|
|
84
107
|
socialLinks?: {
|
|
85
|
-
url: string;
|
|
86
108
|
platform: "github" | "instagram" | "linkedin" | "email" | "website";
|
|
109
|
+
url: string;
|
|
87
110
|
label?: string | undefined;
|
|
88
111
|
}[] | undefined;
|
|
89
112
|
}, {
|
|
@@ -93,8 +116,8 @@ export declare const userSchema: z.ZodObject<{
|
|
|
93
116
|
description?: string | undefined;
|
|
94
117
|
story?: string | undefined;
|
|
95
118
|
socialLinks?: {
|
|
96
|
-
url: string;
|
|
97
119
|
platform: "github" | "instagram" | "linkedin" | "email" | "website";
|
|
120
|
+
url: string;
|
|
98
121
|
label?: string | undefined;
|
|
99
122
|
}[] | undefined;
|
|
100
123
|
}>>;
|
|
@@ -106,7 +129,16 @@ export declare const userSchema: z.ZodObject<{
|
|
|
106
129
|
};
|
|
107
130
|
aiApiKeyOverride?: string | undefined;
|
|
108
131
|
gitSyncTokenOverride?: string | undefined;
|
|
109
|
-
|
|
132
|
+
setup?: {
|
|
133
|
+
email: string;
|
|
134
|
+
delivery: "email";
|
|
135
|
+
} | undefined;
|
|
136
|
+
atproto?: {
|
|
137
|
+
identifier: string;
|
|
138
|
+
} | undefined;
|
|
139
|
+
playbooks?: {
|
|
140
|
+
onboarding?: boolean | undefined;
|
|
141
|
+
} | undefined;
|
|
110
142
|
anchorProfile?: {
|
|
111
143
|
name?: string | undefined;
|
|
112
144
|
email?: string | undefined;
|
|
@@ -114,8 +146,8 @@ export declare const userSchema: z.ZodObject<{
|
|
|
114
146
|
description?: string | undefined;
|
|
115
147
|
story?: string | undefined;
|
|
116
148
|
socialLinks?: {
|
|
117
|
-
url: string;
|
|
118
149
|
platform: "github" | "instagram" | "linkedin" | "email" | "website";
|
|
150
|
+
url: string;
|
|
119
151
|
label?: string | undefined;
|
|
120
152
|
}[] | undefined;
|
|
121
153
|
} | undefined;
|
|
@@ -127,7 +159,16 @@ export declare const userSchema: z.ZodObject<{
|
|
|
127
159
|
};
|
|
128
160
|
aiApiKeyOverride?: string | undefined;
|
|
129
161
|
gitSyncTokenOverride?: string | undefined;
|
|
130
|
-
|
|
162
|
+
setup?: {
|
|
163
|
+
email: string;
|
|
164
|
+
delivery: "email";
|
|
165
|
+
} | undefined;
|
|
166
|
+
atproto?: {
|
|
167
|
+
identifier: string;
|
|
168
|
+
} | undefined;
|
|
169
|
+
playbooks?: {
|
|
170
|
+
onboarding?: boolean | undefined;
|
|
171
|
+
} | undefined;
|
|
131
172
|
anchorProfile?: {
|
|
132
173
|
name?: string | undefined;
|
|
133
174
|
email?: string | undefined;
|
|
@@ -135,8 +176,8 @@ export declare const userSchema: z.ZodObject<{
|
|
|
135
176
|
description?: string | undefined;
|
|
136
177
|
story?: string | undefined;
|
|
137
178
|
socialLinks?: {
|
|
138
|
-
url: string;
|
|
139
179
|
platform: "github" | "instagram" | "linkedin" | "email" | "website";
|
|
180
|
+
url: string;
|
|
140
181
|
label?: string | undefined;
|
|
141
182
|
}[] | undefined;
|
|
142
183
|
} | undefined;
|
|
@@ -147,33 +188,28 @@ export declare const cohortSchema: z.ZodEffects<z.ZodObject<{
|
|
|
147
188
|
presetOverride: z.ZodOptional<z.ZodEnum<["core", "default", "pro"]>>;
|
|
148
189
|
aiApiKeyOverride: z.ZodOptional<z.ZodString>;
|
|
149
190
|
gitSyncTokenOverride: z.ZodOptional<z.ZodString>;
|
|
150
|
-
mcpAuthTokenOverride: z.ZodOptional<z.ZodString>;
|
|
151
191
|
}, "strict", z.ZodTypeAny, {
|
|
152
192
|
members: string[];
|
|
153
193
|
aiApiKeyOverride?: string | undefined;
|
|
154
194
|
gitSyncTokenOverride?: string | undefined;
|
|
155
|
-
mcpAuthTokenOverride?: string | undefined;
|
|
156
195
|
brainVersionOverride?: string | undefined;
|
|
157
196
|
presetOverride?: "default" | "core" | "pro" | undefined;
|
|
158
197
|
}, {
|
|
159
198
|
members: string[];
|
|
160
199
|
aiApiKeyOverride?: string | undefined;
|
|
161
200
|
gitSyncTokenOverride?: string | undefined;
|
|
162
|
-
mcpAuthTokenOverride?: string | undefined;
|
|
163
201
|
brainVersionOverride?: string | undefined;
|
|
164
202
|
presetOverride?: "default" | "core" | "pro" | undefined;
|
|
165
203
|
}>, {
|
|
166
204
|
members: string[];
|
|
167
205
|
aiApiKeyOverride?: string | undefined;
|
|
168
206
|
gitSyncTokenOverride?: string | undefined;
|
|
169
|
-
mcpAuthTokenOverride?: string | undefined;
|
|
170
207
|
brainVersionOverride?: string | undefined;
|
|
171
208
|
presetOverride?: "default" | "core" | "pro" | undefined;
|
|
172
209
|
}, {
|
|
173
210
|
members: string[];
|
|
174
211
|
aiApiKeyOverride?: string | undefined;
|
|
175
212
|
gitSyncTokenOverride?: string | undefined;
|
|
176
|
-
mcpAuthTokenOverride?: string | undefined;
|
|
177
213
|
brainVersionOverride?: string | undefined;
|
|
178
214
|
presetOverride?: "default" | "core" | "pro" | undefined;
|
|
179
215
|
}>;
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import { z } from "@brains/utils";
|
|
1
|
+
import { z } from "@brains/utils/zod";
|
|
2
2
|
declare const encryptedUserSecretsSchema: z.ZodObject<{
|
|
3
3
|
gitSyncToken: z.ZodOptional<z.ZodString>;
|
|
4
|
-
mcpAuthToken: z.ZodOptional<z.ZodString>;
|
|
5
4
|
discordBotToken: z.ZodOptional<z.ZodString>;
|
|
6
5
|
aiApiKey: z.ZodOptional<z.ZodString>;
|
|
6
|
+
atprotoAppPassword: z.ZodOptional<z.ZodString>;
|
|
7
7
|
}, "strict", z.ZodTypeAny, {
|
|
8
8
|
aiApiKey?: string | undefined;
|
|
9
9
|
gitSyncToken?: string | undefined;
|
|
10
|
-
mcpAuthToken?: string | undefined;
|
|
11
10
|
discordBotToken?: string | undefined;
|
|
11
|
+
atprotoAppPassword?: string | undefined;
|
|
12
12
|
}, {
|
|
13
13
|
aiApiKey?: string | undefined;
|
|
14
14
|
gitSyncToken?: string | undefined;
|
|
15
|
-
mcpAuthToken?: string | undefined;
|
|
16
15
|
discordBotToken?: string | undefined;
|
|
16
|
+
atprotoAppPassword?: string | undefined;
|
|
17
17
|
}>;
|
|
18
18
|
export type EncryptedUserSecrets = z.infer<typeof encryptedUserSecretsSchema>;
|
|
19
19
|
export interface SecretsEncryptOptions {
|
|
@@ -1,26 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { type RunCommand } from "./run-subprocess";
|
|
3
|
-
export interface SshKeyBootstrapOptions {
|
|
4
|
-
env?: NodeJS.ProcessEnv | undefined;
|
|
5
|
-
fetchImpl?: FetchLike | undefined;
|
|
6
|
-
logger?: (message: string) => void;
|
|
7
|
-
pushTo?: string | undefined;
|
|
8
|
-
runCommand?: RunCommand | undefined;
|
|
9
|
-
sshKeygen?: SshKeygen | undefined;
|
|
10
|
-
}
|
|
11
|
-
export interface SshKeyBootstrapResult {
|
|
12
|
-
createdHetznerKey: boolean;
|
|
13
|
-
createdLocalKey: boolean;
|
|
14
|
-
privateKeyPath: string;
|
|
15
|
-
publicKeyPath: string;
|
|
16
|
-
sshKeyName: string;
|
|
17
|
-
}
|
|
18
|
-
export interface SshKeygen {
|
|
19
|
-
createEd25519KeyPair: (privateKeyPath: string, comment: string) => void;
|
|
20
|
-
derivePublicKey: (privateKeyPath: string) => string;
|
|
21
|
-
}
|
|
22
|
-
export declare function runPilotSshKeyBootstrap(rootDir: string, options?: SshKeyBootstrapOptions): Promise<{
|
|
23
|
-
success: boolean;
|
|
24
|
-
message?: string;
|
|
25
|
-
}>;
|
|
26
|
-
export declare function bootstrapPilotSshKey(rootDir: string, options?: SshKeyBootstrapOptions): Promise<SshKeyBootstrapResult>;
|
|
1
|
+
export { bootstrapSshKey as bootstrapPilotSshKey, runSshKeyBootstrap as runPilotSshKeyBootstrap, type SshKeyBootstrapOptions, type SshKeyBootstrapResult, type SshKeygen, } from "@brains/deploy-support/ssh-key-bootstrap";
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface AddPilotUserOptions {
|
|
2
|
+
cohort: string;
|
|
3
|
+
anchorId?: string | undefined;
|
|
4
|
+
}
|
|
5
|
+
export interface AddPilotUserResult {
|
|
6
|
+
handle: string;
|
|
7
|
+
cohort: string;
|
|
8
|
+
userPath: string;
|
|
9
|
+
secretsTemplatePath: string;
|
|
10
|
+
cohortPath: string;
|
|
11
|
+
createdUser: boolean;
|
|
12
|
+
createdSecretsTemplate: boolean;
|
|
13
|
+
addedToCohort: boolean;
|
|
14
|
+
}
|
|
15
|
+
export declare function addPilotUser(rootDir: string, handle: string, options: AddPilotUserOptions): Promise<AddPilotUserResult>;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { FetchLike } from "@brains/deploy-support/origin-ca";
|
|
2
|
+
import { type ResolvedUser } from "./load-registry";
|
|
3
|
+
export interface VerifyPilotUserOptions {
|
|
4
|
+
fetchImpl?: FetchLike;
|
|
5
|
+
logger?: (message: string) => void;
|
|
6
|
+
}
|
|
7
|
+
export interface FailedCheck {
|
|
8
|
+
name: string;
|
|
9
|
+
message: string;
|
|
10
|
+
}
|
|
11
|
+
export interface VerifyPilotUserResult {
|
|
12
|
+
handle: string;
|
|
13
|
+
preset: ResolvedUser["preset"];
|
|
14
|
+
domain: string;
|
|
15
|
+
contentRepo: string;
|
|
16
|
+
checks: string[];
|
|
17
|
+
failedChecks: FailedCheck[];
|
|
18
|
+
}
|
|
19
|
+
export declare function verifyPilotUser(rootDir: string, handle: string, options?: VerifyPilotUserOptions): Promise<VerifyPilotUserResult>;
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
7
|
-
"version": "0.2.0-alpha.
|
|
7
|
+
"version": "0.2.0-alpha.141",
|
|
8
8
|
"type": "module",
|
|
9
9
|
"exports": {
|
|
10
10
|
".": {
|
|
@@ -30,14 +30,16 @@
|
|
|
30
30
|
"build": "bun scripts/build.ts",
|
|
31
31
|
"prepublishOnly": "bun scripts/build.ts",
|
|
32
32
|
"typecheck": "tsc --noEmit",
|
|
33
|
-
"lint": "eslint . --ext .ts",
|
|
34
|
-
"lint:fix": "eslint . --ext .ts --fix",
|
|
35
|
-
"test": "bun test --timeout 20000"
|
|
33
|
+
"lint": "eslint . --ext .ts,.tsx --max-warnings 0",
|
|
34
|
+
"lint:fix": "eslint . --ext .ts,.tsx --max-warnings 0 --fix",
|
|
35
|
+
"test": "bun run build && bun test --timeout 20000",
|
|
36
|
+
"test:smoke": "bun run build && RUN_SMOKE_TESTS=1 bun test --timeout 60000"
|
|
36
37
|
},
|
|
37
38
|
"dependencies": {
|
|
38
39
|
"age-encryption": "^0.3.0"
|
|
39
40
|
},
|
|
40
41
|
"devDependencies": {
|
|
42
|
+
"@brains/deploy-support": "workspace:*",
|
|
41
43
|
"@brains/eslint-config": "workspace:*",
|
|
42
44
|
"@brains/typescript-config": "workspace:*",
|
|
43
45
|
"@brains/utils": "workspace:*",
|
|
@@ -14,16 +14,30 @@ AI_API_KEY=
|
|
|
14
14
|
# @required @sensitive
|
|
15
15
|
GIT_SYNC_TOKEN=
|
|
16
16
|
|
|
17
|
-
#
|
|
18
|
-
#
|
|
17
|
+
# Content repo administration
|
|
18
|
+
# Local/operator secret only. Used by brains-ops to create missing GitHub repos;
|
|
19
|
+
# do not deploy it into Rover runtime config.
|
|
19
20
|
# @required @sensitive
|
|
20
|
-
|
|
21
|
+
CONTENT_REPO_ADMIN_TOKEN=
|
|
21
22
|
|
|
22
23
|
# Discord (optional, per-user)
|
|
23
24
|
# Comes from the decrypted users/<handle>.secrets.yaml.age file when enabled.
|
|
24
25
|
# @sensitive
|
|
25
26
|
DISCORD_BOT_TOKEN=
|
|
26
27
|
|
|
28
|
+
# AT Protocol publishing/discovery (optional, per-user)
|
|
29
|
+
# Comes from the decrypted users/<handle>.secrets.yaml.age file when configured.
|
|
30
|
+
# @sensitive
|
|
31
|
+
ATPROTO_APP_PASSWORD=
|
|
32
|
+
|
|
33
|
+
# Setup email delivery (optional, shared)
|
|
34
|
+
# Used when a user file declares setup.delivery: email.
|
|
35
|
+
# @sensitive
|
|
36
|
+
SETUP_EMAIL_API_KEY=
|
|
37
|
+
|
|
38
|
+
# @sensitive
|
|
39
|
+
SETUP_EMAIL_FROM=
|
|
40
|
+
|
|
27
41
|
# ---- deploy/provision vars ----
|
|
28
42
|
|
|
29
43
|
# @required @sensitive
|
|
@@ -2,6 +2,11 @@ name: Build
|
|
|
2
2
|
|
|
3
3
|
on:
|
|
4
4
|
workflow_dispatch:
|
|
5
|
+
inputs:
|
|
6
|
+
brain_version:
|
|
7
|
+
description: Brain version to build; defaults to pilot.yaml brainVersion
|
|
8
|
+
required: false
|
|
9
|
+
type: string
|
|
5
10
|
push:
|
|
6
11
|
branches: ["main"]
|
|
7
12
|
paths:
|
|
@@ -23,7 +28,10 @@ jobs:
|
|
|
23
28
|
|
|
24
29
|
- name: Extract image metadata inputs
|
|
25
30
|
run: |
|
|
26
|
-
BRAIN_VERSION="$
|
|
31
|
+
BRAIN_VERSION="${{ inputs.brain_version || '' }}"
|
|
32
|
+
if [ -z "$BRAIN_VERSION" ]; then
|
|
33
|
+
BRAIN_VERSION="$(grep '^brainVersion:' pilot.yaml | sed 's/^brainVersion:[[:space:]]*//' | tr -d '"' | tr -d "'")"
|
|
34
|
+
fi
|
|
27
35
|
if [ -z "$BRAIN_VERSION" ]; then
|
|
28
36
|
echo "Missing brainVersion in pilot.yaml" >&2
|
|
29
37
|
exit 1
|
|
@@ -32,25 +40,25 @@ jobs:
|
|
|
32
40
|
echo "IMAGE_REPOSITORY=ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }}" >> "$GITHUB_ENV"
|
|
33
41
|
|
|
34
42
|
- name: Set up Docker Buildx
|
|
35
|
-
uses: docker/setup-buildx-action@
|
|
43
|
+
uses: docker/setup-buildx-action@v4
|
|
36
44
|
|
|
37
45
|
- name: Extract image metadata
|
|
38
46
|
id: meta
|
|
39
|
-
uses: docker/metadata-action@
|
|
47
|
+
uses: docker/metadata-action@v6
|
|
40
48
|
with:
|
|
41
49
|
images: ${{ env.IMAGE_REPOSITORY }}
|
|
42
50
|
tags: |
|
|
43
51
|
type=raw,value=brain-${{ env.BRAIN_VERSION }}
|
|
44
52
|
|
|
45
53
|
- name: Log in to GHCR
|
|
46
|
-
uses: docker/login-action@
|
|
54
|
+
uses: docker/login-action@v4
|
|
47
55
|
with:
|
|
48
56
|
registry: ghcr.io
|
|
49
57
|
username: ${{ github.actor }}
|
|
50
58
|
password: ${{ secrets.GITHUB_TOKEN }}
|
|
51
59
|
|
|
52
60
|
- name: Build and push image
|
|
53
|
-
uses: docker/build-push-action@
|
|
61
|
+
uses: docker/build-push-action@v7
|
|
54
62
|
with:
|
|
55
63
|
context: .
|
|
56
64
|
file: deploy/Dockerfile
|
|
@@ -16,6 +16,10 @@ on:
|
|
|
16
16
|
- users/*.secrets.yaml.age
|
|
17
17
|
- deploy/**
|
|
18
18
|
- .github/workflows/deploy.yml
|
|
19
|
+
workflow_run:
|
|
20
|
+
workflows: [Reconcile]
|
|
21
|
+
types: [completed]
|
|
22
|
+
branches: [main]
|
|
19
23
|
|
|
20
24
|
permissions:
|
|
21
25
|
contents: write
|
|
@@ -23,13 +27,16 @@ permissions:
|
|
|
23
27
|
|
|
24
28
|
jobs:
|
|
25
29
|
resolve_handles:
|
|
30
|
+
if: >
|
|
31
|
+
github.event_name != 'workflow_run' ||
|
|
32
|
+
github.event.workflow_run.conclusion == 'success'
|
|
26
33
|
runs-on: ubuntu-latest
|
|
27
34
|
outputs:
|
|
28
35
|
handles_json: ${{ steps.resolve.outputs.handles_json }}
|
|
29
36
|
steps:
|
|
30
37
|
- uses: actions/checkout@v5
|
|
31
38
|
with:
|
|
32
|
-
ref: ${{ github.sha }}
|
|
39
|
+
ref: ${{ github.event_name == 'workflow_run' && github.event.workflow_run.head_branch || github.sha }}
|
|
33
40
|
fetch-depth: 0
|
|
34
41
|
|
|
35
42
|
- uses: oven-sh/setup-bun@v2
|
|
@@ -41,7 +48,7 @@ jobs:
|
|
|
41
48
|
id: resolve
|
|
42
49
|
env:
|
|
43
50
|
HANDLE_INPUT: ${{ inputs.handle || '' }}
|
|
44
|
-
BEFORE_SHA: ${{ github.event.before || '' }}
|
|
51
|
+
BEFORE_SHA: ${{ github.event_name == 'workflow_run' && github.event.workflow_run.head_sha || github.event.before || '' }}
|
|
45
52
|
run: bun deploy/scripts/resolve-deploy-handles.ts
|
|
46
53
|
|
|
47
54
|
no_changes:
|
|
@@ -68,7 +75,7 @@ jobs:
|
|
|
68
75
|
steps:
|
|
69
76
|
- uses: actions/checkout@v5
|
|
70
77
|
with:
|
|
71
|
-
ref: ${{ github.sha }}
|
|
78
|
+
ref: ${{ github.event_name == 'workflow_run' && github.event.workflow_run.head_branch || github.sha }}
|
|
72
79
|
|
|
73
80
|
- uses: oven-sh/setup-bun@v2
|
|
74
81
|
|
|
@@ -96,7 +103,8 @@ jobs:
|
|
|
96
103
|
env:
|
|
97
104
|
SHARED_AI_API_KEY: ${{ secrets[steps.user_secrets.outputs.shared_ai_api_key_secret_name] }}
|
|
98
105
|
SHARED_GIT_SYNC_TOKEN: ${{ secrets[steps.user_secrets.outputs.shared_git_sync_token_secret_name] }}
|
|
99
|
-
|
|
106
|
+
SETUP_EMAIL_API_KEY: ${{ secrets.SETUP_EMAIL_API_KEY }}
|
|
107
|
+
SETUP_EMAIL_FROM: ${{ secrets.SETUP_EMAIL_FROM }}
|
|
100
108
|
HCLOUD_TOKEN: ${{ secrets.HCLOUD_TOKEN }}
|
|
101
109
|
HCLOUD_SSH_KEY_NAME: ${{ secrets.HCLOUD_SSH_KEY_NAME }}
|
|
102
110
|
HCLOUD_SERVER_TYPE: ${{ secrets.HCLOUD_SERVER_TYPE }}
|
|
@@ -110,7 +118,6 @@ jobs:
|
|
|
110
118
|
run: |
|
|
111
119
|
export AI_API_KEY="${AI_API_KEY:-$SHARED_AI_API_KEY}"
|
|
112
120
|
export GIT_SYNC_TOKEN="${GIT_SYNC_TOKEN:-$SHARED_GIT_SYNC_TOKEN}"
|
|
113
|
-
export MCP_AUTH_TOKEN="${MCP_AUTH_TOKEN:-$SHARED_MCP_AUTH_TOKEN}"
|
|
114
121
|
bun deploy/scripts/validate-secrets.ts
|
|
115
122
|
|
|
116
123
|
- name: Seed content repo
|
|
@@ -122,7 +129,7 @@ jobs:
|
|
|
122
129
|
bun deploy/scripts/sync-content-repo.ts
|
|
123
130
|
|
|
124
131
|
- name: Log in to GHCR
|
|
125
|
-
uses: docker/login-action@
|
|
132
|
+
uses: docker/login-action@v4
|
|
126
133
|
with:
|
|
127
134
|
registry: ghcr.io
|
|
128
135
|
username: ${{ github.actor }}
|
|
@@ -168,14 +175,14 @@ jobs:
|
|
|
168
175
|
env:
|
|
169
176
|
SHARED_AI_API_KEY: ${{ secrets[steps.user_secrets.outputs.shared_ai_api_key_secret_name] }}
|
|
170
177
|
SHARED_GIT_SYNC_TOKEN: ${{ secrets[steps.user_secrets.outputs.shared_git_sync_token_secret_name] }}
|
|
171
|
-
|
|
178
|
+
SETUP_EMAIL_API_KEY: ${{ secrets.SETUP_EMAIL_API_KEY }}
|
|
179
|
+
SETUP_EMAIL_FROM: ${{ secrets.SETUP_EMAIL_FROM }}
|
|
172
180
|
KAMAL_REGISTRY_PASSWORD: ${{ secrets.KAMAL_REGISTRY_PASSWORD }}
|
|
173
181
|
CERTIFICATE_PEM: ${{ secrets.CERTIFICATE_PEM }}
|
|
174
182
|
PRIVATE_KEY_PEM: ${{ secrets.PRIVATE_KEY_PEM }}
|
|
175
183
|
run: |
|
|
176
184
|
export AI_API_KEY="${AI_API_KEY:-$SHARED_AI_API_KEY}"
|
|
177
185
|
export GIT_SYNC_TOKEN="${GIT_SYNC_TOKEN:-$SHARED_GIT_SYNC_TOKEN}"
|
|
178
|
-
export MCP_AUTH_TOKEN="${MCP_AUTH_TOKEN:-$SHARED_MCP_AUTH_TOKEN}"
|
|
179
186
|
bun deploy/scripts/write-kamal-secrets.ts
|
|
180
187
|
|
|
181
188
|
- name: Provision server
|
|
@@ -271,7 +278,7 @@ jobs:
|
|
|
271
278
|
steps:
|
|
272
279
|
- uses: actions/checkout@v5
|
|
273
280
|
with:
|
|
274
|
-
ref: ${{ github.sha }}
|
|
281
|
+
ref: ${{ github.event_name == 'workflow_run' && github.event.workflow_run.head_branch || github.sha }}
|
|
275
282
|
|
|
276
283
|
- uses: oven-sh/setup-bun@v2
|
|
277
284
|
|
|
@@ -293,8 +300,22 @@ jobs:
|
|
|
293
300
|
if git diff --quiet -- users views; then
|
|
294
301
|
exit 0
|
|
295
302
|
fi
|
|
303
|
+
|
|
304
|
+
git fetch origin "${{ github.ref_name }}"
|
|
305
|
+
if git diff --quiet "origin/${{ github.ref_name }}" -- users views; then
|
|
306
|
+
exit 0
|
|
307
|
+
fi
|
|
308
|
+
|
|
309
|
+
patch_file="$(mktemp)"
|
|
310
|
+
git diff --binary -- users views > "$patch_file"
|
|
311
|
+
git reset --hard "origin/${{ github.ref_name }}"
|
|
312
|
+
git apply --3way --index "$patch_file"
|
|
313
|
+
|
|
314
|
+
if git diff --cached --quiet -- users views; then
|
|
315
|
+
exit 0
|
|
316
|
+
fi
|
|
317
|
+
|
|
296
318
|
git config user.name "github-actions[bot]"
|
|
297
319
|
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
|
298
|
-
git add users views
|
|
299
320
|
git commit -m "chore(ops): reconcile generated config"
|
|
300
321
|
git push origin HEAD:${{ github.ref_name }}
|
|
@@ -38,8 +38,22 @@ jobs:
|
|
|
38
38
|
if git diff --quiet -- views users; then
|
|
39
39
|
exit 0
|
|
40
40
|
fi
|
|
41
|
+
|
|
42
|
+
git fetch origin "${{ github.ref_name }}"
|
|
43
|
+
if git diff --quiet "origin/${{ github.ref_name }}" -- views users; then
|
|
44
|
+
exit 0
|
|
45
|
+
fi
|
|
46
|
+
|
|
47
|
+
patch_file="$(mktemp)"
|
|
48
|
+
git diff --binary -- views users > "$patch_file"
|
|
49
|
+
git reset --hard "origin/${{ github.ref_name }}"
|
|
50
|
+
git apply --3way --index "$patch_file"
|
|
51
|
+
|
|
52
|
+
if git diff --cached --quiet -- views users; then
|
|
53
|
+
exit 0
|
|
54
|
+
fi
|
|
55
|
+
|
|
41
56
|
git config user.name "github-actions[bot]"
|
|
42
57
|
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
|
43
|
-
git add views users
|
|
44
58
|
git commit -m "chore(ops): reconcile pilot outputs"
|
|
45
|
-
git push
|
|
59
|
+
git push origin HEAD:${{ github.ref_name }}
|
|
@@ -29,6 +29,7 @@ The repo also checks in its deploy contract:
|
|
|
29
29
|
- `.github/workflows/*`
|
|
30
30
|
|
|
31
31
|
`.env.schema` is the single source of truth for required and sensitive deploy vars.
|
|
32
|
+
Use separate GitHub tokens: `CONTENT_REPO_ADMIN_TOKEN` for operator-side content repo creation/checks, and `GIT_SYNC_TOKEN` for runtime directory-sync git access.
|
|
32
33
|
The shared pilot image tag is `brain-${brainVersion}` end to end.
|
|
33
34
|
When `pilot.yaml.brainVersion` changes and you push, CI rebuilds the shared tag, refreshes generated user env files, and redeploys affected users.
|
|
34
35
|
When a push changes only deploy contract files, CI prints `No affected user configs; skipping deploy.` and stops before Kamal.
|
|
@@ -37,7 +38,8 @@ When a push changes only deploy contract files, CI prints `No affected user conf
|
|
|
37
38
|
|
|
38
39
|
- `brains-ops init <repo>`
|
|
39
40
|
- `brains-ops render <repo>` — regenerates `views/users.md` with live DNS, `/health`, and unauthenticated `/mcp` status checks
|
|
40
|
-
- `brains-ops
|
|
41
|
+
- `brains-ops user:add <repo> <handle> --cohort <cohort>` — scaffolds a user file, per-user secrets template, and cohort membership
|
|
42
|
+
- `brains-ops onboard <repo> <handle>` — creates/seeds the user's content repo with separate admin and sync tokens
|
|
41
43
|
- `brains-ops age-key:bootstrap <repo>`
|
|
42
44
|
- `brains-ops ssh-key:bootstrap <repo>`
|
|
43
45
|
- `brains-ops cert:bootstrap <repo>`
|