@layers/amba 1.1.0 → 4.0.3

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.
@@ -0,0 +1,259 @@
1
+ /**
2
+ * Two-scope credential model for `amba init`.
3
+ *
4
+ * Identity is **developer-scoped** (one machine identity, persisted in
5
+ * `~/.amba/credentials.json`). State is **project-scoped** (one per
6
+ * project directory, persisted in `<cwd>/.amba/project.json`).
7
+ *
8
+ * One Amba account can own N projects. Running `amba init` in five
9
+ * different folders under one identity yields one developer row + five
10
+ * project rows — exactly the model `apps/console` and the API enforce.
11
+ *
12
+ * Backward compatibility
13
+ * ----------------------
14
+ * The legacy `~/.amba/credentials.json` (browser-OAuth era) carried
15
+ * `{ access_token, refresh_token, expires_at }`. We read both shapes —
16
+ * a missing `version` key signals legacy and triggers a one-shot
17
+ * in-place upgrade after the first successful `developer_me` verify.
18
+ *
19
+ * Idempotency
20
+ * -----------
21
+ * `ensureDeveloperIdentity` + `ensureProjectForCwd` are the two entry
22
+ * points. Both are safe to call on every `amba init` run:
23
+ * - identity: load → verify → upgrade-or-keep; only signs up if no
24
+ * verified PAT exists anywhere.
25
+ * - project: load `<cwd>/.amba/project.json` → verify the
26
+ * `project_id` still belongs to the current developer; if missing
27
+ * or stale, mint a new project under the dev's identity.
28
+ */
29
+ /**
30
+ * Developer identity stored at `~/.amba/credentials.json`.
31
+ *
32
+ * One per machine. Persists across project folders and re-runs.
33
+ */
34
+ export interface DeveloperCredentials {
35
+ /** Schema version — increments when the shape changes incompatibly. */
36
+ version: 1;
37
+ /** Developer UUID from the control DB. Populated post-verify. */
38
+ developer_id: string | null;
39
+ /** Email on the developer row. May be auto-generated for sandbox accounts. */
40
+ email: string;
41
+ /** Personal Access Token (`amb_dpat_…`). Long-lived. */
42
+ pat: string;
43
+ /** API root the PAT was minted against. */
44
+ api_url: string;
45
+ /** How this identity was created. */
46
+ source: 'sandbox-init' | 'browser-auth' | 'manual' | 'legacy';
47
+ /** ISO timestamp when this record was written/upgraded. */
48
+ created_at: string;
49
+ /** Mirrors `pat`. */
50
+ access_token: string;
51
+ /** Empty string — PATs don't refresh. */
52
+ refresh_token: '';
53
+ /** Far-future ISO timestamp — PATs don't expire on the client side. */
54
+ expires_at: string;
55
+ }
56
+ /**
57
+ * Project state stored at `<cwd>/.amba/project.json`.
58
+ *
59
+ * One per project directory. Tracks which project this folder is
60
+ * attached to (so re-running `amba init` in the same folder is
61
+ * idempotent) plus the credentials needed for SDK init.
62
+ */
63
+ export interface ProjectCredentials {
64
+ version: 1;
65
+ project_id: string;
66
+ project_name: string;
67
+ environment: 'development' | 'production';
68
+ client_key: string;
69
+ /** Server key — present when minted. Used by Node SDK / server code. */
70
+ server_key: string | null;
71
+ api_url: string;
72
+ /**
73
+ * List of Amba surfaces this project has been wired up with via the
74
+ * skill (e.g. `['identity','streaks','achievements']`). The skill
75
+ * consults this on re-runs to avoid re-creating existing resources.
76
+ */
77
+ wired_surfaces: string[];
78
+ created_at: string;
79
+ updated_at: string;
80
+ }
81
+ /**
82
+ * Result returned by `verifyPat`. Subset of the API's
83
+ * `GET /v1/auth/developer/me` response — only the fields the CLI
84
+ * actually consumes.
85
+ */
86
+ export interface DeveloperMeResult {
87
+ id: string;
88
+ email: string;
89
+ name?: string;
90
+ }
91
+ export declare function developerCredentialsPath(homeDir?: string): string;
92
+ export declare function projectCredentialsPath(cwd: string): string;
93
+ /**
94
+ * Read `~/.amba/credentials.json`. Returns null when the file is
95
+ * missing, malformed, or empty. Handles both new (versioned) and
96
+ * legacy shapes — legacy returns `version: 1` after migration but
97
+ * with `source: 'legacy'` so callers can tell.
98
+ *
99
+ * Does NOT verify the PAT against the API. Caller must follow up
100
+ * with `verifyPat` before trusting the identity.
101
+ */
102
+ export declare function loadDeveloperCredentials(options?: {
103
+ homeDir?: string;
104
+ }): Promise<DeveloperCredentials | null>;
105
+ /**
106
+ * Atomically write developer credentials to `~/.amba/credentials.json`
107
+ * with mode 0600. Writes to a sibling `.tmp` first and renames into
108
+ * place so a crash mid-write doesn't leave the file empty.
109
+ *
110
+ * Backs up an existing file when its `source` is not one of the
111
+ * managed sources OR when the existing PAT differs from the one being
112
+ * written. The backup goes to `credentials.json.bak-<unix-ms>`.
113
+ */
114
+ export declare function writeDeveloperCredentials(creds: DeveloperCredentials, options?: {
115
+ homeDir?: string;
116
+ }): Promise<{
117
+ path: string;
118
+ backedUpTo: string | null;
119
+ }>;
120
+ export declare function loadProjectCredentials(cwd: string): Promise<ProjectCredentials | null>;
121
+ export declare function writeProjectCredentials(cwd: string, creds: ProjectCredentials): Promise<string>;
122
+ /**
123
+ * Verify a PAT by calling `GET /v1/auth/developer/me`. Returns the
124
+ * developer row on success, `null` on 401/403/404 (PAT invalid or
125
+ * developer not found), or throws on network / 5xx errors.
126
+ *
127
+ * This is the single source of truth for "do we have a working
128
+ * identity." Used at the top of every init run.
129
+ */
130
+ export declare function verifyPat(pat: string, options?: {
131
+ apiUrl?: string;
132
+ fetchImpl?: typeof fetch;
133
+ }): Promise<DeveloperMeResult | null>;
134
+ export interface EnsureDeveloperOptions {
135
+ homeDir?: string;
136
+ apiUrl?: string;
137
+ fetchImpl?: typeof fetch;
138
+ /**
139
+ * When true, never call signup — if the existing credential is
140
+ * invalid, throw instead. Used by the interactive (non-headless)
141
+ * init path where the user expects a browser-auth fallback.
142
+ */
143
+ signupOnMissing?: boolean;
144
+ /**
145
+ * Optional override for the auto-generated sandbox email. Surfaced
146
+ * by the CLI's `--email <addr>` flag for tests + manual sandbox
147
+ * provisioning under a known address. Ignored when an existing
148
+ * identity is reused.
149
+ */
150
+ sandboxEmail?: string;
151
+ }
152
+ export interface EnsureDeveloperResult {
153
+ credentials: DeveloperCredentials;
154
+ /** True when we minted a fresh sandbox account this run. */
155
+ newlySignedUp: boolean;
156
+ /** Verified developer row from the API. */
157
+ developer: DeveloperMeResult;
158
+ /**
159
+ * The first project minted by signup, when `newlySignedUp` is true.
160
+ * Null when we re-used an existing identity — caller is expected to
161
+ * mint a new project under it via `ensureProjectForCwd`.
162
+ */
163
+ firstProject: {
164
+ project_id: string;
165
+ client_key: string;
166
+ server_key: string | null;
167
+ provisioning_status?: string;
168
+ verify_url?: string;
169
+ } | null;
170
+ /**
171
+ * Absolute path of a backup file written when an existing credential
172
+ * was overwritten with a new one (different PAT). Null when no backup
173
+ * was needed (no prior file, same PAT verified, etc.).
174
+ */
175
+ credentialsBackedUpTo: string | null;
176
+ /** Absolute path of `~/.amba/credentials.json`. */
177
+ credentialsPath: string;
178
+ }
179
+ /**
180
+ * Ensure the machine has a verified Amba developer identity.
181
+ *
182
+ * Decision tree:
183
+ * 1. Load existing `~/.amba/credentials.json`.
184
+ * 2. If found, verify the PAT via `developer/me`.
185
+ * - Valid → migrate shape if legacy, return.
186
+ * - Invalid → fall through to signup (unless `signupOnMissing: false`).
187
+ * 3. No creds (or invalid) + `signupOnMissing !== false` → call
188
+ * `performSandboxSignup` with generated email/password, write the
189
+ * result, return.
190
+ * 4. No creds + `signupOnMissing === false` → throw.
191
+ */
192
+ export declare function ensureDeveloperIdentity(options?: EnsureDeveloperOptions): Promise<EnsureDeveloperResult>;
193
+ export interface EnsureProjectOptions {
194
+ /** Inject the dev-identity PAT into the api-client. */
195
+ pat: string;
196
+ /**
197
+ * When provided, attach this folder to the named project ID
198
+ * instead of creating a new one (e.g. user passed `--project-id`).
199
+ */
200
+ attachToProjectId?: string;
201
+ /**
202
+ * Default project name when minting. Defaults to `basename(cwd)`.
203
+ */
204
+ defaultName?: string;
205
+ /** `'development'` (default) or `'production'`. */
206
+ environment?: 'development' | 'production';
207
+ /**
208
+ * Optional pre-minted first-project payload from a sandbox-signup
209
+ * response. When provided AND no project.json exists yet, we use
210
+ * this without an extra `createProject` call. Saves a round-trip
211
+ * on the first-ever init.
212
+ */
213
+ signupFirstProject?: {
214
+ project_id: string;
215
+ client_key: string;
216
+ server_key: string | null;
217
+ };
218
+ }
219
+ export interface EnsureProjectResult {
220
+ credentials: ProjectCredentials;
221
+ /** True when we minted a new project this run. */
222
+ newlyCreated: boolean;
223
+ }
224
+ /**
225
+ * Ensure the current working directory is attached to an Amba project.
226
+ *
227
+ * Decision tree:
228
+ * 1. Load existing `<cwd>/.amba/project.json`.
229
+ * - Present → return (no API call; we trust the file's metadata
230
+ * until something downstream fails, at which point the caller
231
+ * re-keys).
232
+ * 2. Missing + `signupFirstProject` provided → use those keys, write
233
+ * `<cwd>/.amba/project.json`, return (newlyCreated=true).
234
+ * 3. Missing + no signup payload + `attachToProjectId` provided →
235
+ * mint a new client+server key under that project, write the
236
+ * file, return.
237
+ * 4. Missing + no signup payload + no attach → call
238
+ * `createProject({ name, environment })` under the dev's PAT,
239
+ * mint both keys, write the file, return.
240
+ */
241
+ export declare function ensureProjectForCwd(cwd: string, options: EnsureProjectOptions): Promise<EnsureProjectResult>;
242
+ /**
243
+ * Sanitize a candidate project name. The control-plane enforces
244
+ * `^[a-zA-Z0-9-_]{1,64}$` (see `apps/api/src/routes/projects.ts`); the
245
+ * basename of a project folder often contains spaces or dots. We
246
+ * collapse runs of non-allowed chars to `-`, trim outer dashes, and
247
+ * truncate to 64.
248
+ */
249
+ export declare function sanitizeProjectName(input: string): string;
250
+ /**
251
+ * Update an existing `<cwd>/.amba/project.json` to record additional
252
+ * surfaces the skill has wired up. Used by the Amba skill after each
253
+ * `amba_<surface>_create` call lands so re-runs can skip already-done
254
+ * work. Bumps `updated_at`. Silently no-ops if the file is missing
255
+ * (skill should always run after `amba init`).
256
+ */
257
+ export declare function recordWiredSurface(cwd: string, surface: string): Promise<void>;
258
+ /** True iff a `<cwd>/.amba/project.json` exists and parses. */
259
+ export declare function projectIsLinked(cwd: string): Promise<boolean>;