@layers/amba 4.1.5 → 4.1.6
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/api-client.d.ts +9 -1
- package/dist/commands/projects.d.ts +9 -2
- package/dist/index.js +32 -11
- package/package.json +3 -3
- package/skill-bundle/references/identity.md +15 -3
package/dist/api-client.d.ts
CHANGED
|
@@ -21,6 +21,8 @@ export interface ProjectSummary {
|
|
|
21
21
|
environment?: string;
|
|
22
22
|
bundle_id?: string | null;
|
|
23
23
|
google_oauth_client_id?: string | null;
|
|
24
|
+
magic_link_redirect_url?: string | null;
|
|
25
|
+
auth_email_brand_name?: string | null;
|
|
24
26
|
status?: string;
|
|
25
27
|
created_at?: string;
|
|
26
28
|
/** Persisted subscription/accounting tier. */
|
|
@@ -71,6 +73,8 @@ export declare function updateProject(projectId: string, patch: {
|
|
|
71
73
|
name?: string;
|
|
72
74
|
bundle_id?: string | null;
|
|
73
75
|
google_oauth_client_id?: string | null;
|
|
76
|
+
magic_link_redirect_url?: string | null;
|
|
77
|
+
auth_email_brand_name?: string | null;
|
|
74
78
|
platform?: string;
|
|
75
79
|
environment?: string;
|
|
76
80
|
}): Promise<ApiResponse<{
|
|
@@ -78,6 +82,8 @@ export declare function updateProject(projectId: string, patch: {
|
|
|
78
82
|
name: string;
|
|
79
83
|
bundle_id: string | null;
|
|
80
84
|
google_oauth_client_id: string | null;
|
|
85
|
+
magic_link_redirect_url: string | null;
|
|
86
|
+
auth_email_brand_name: string | null;
|
|
81
87
|
platform: string;
|
|
82
88
|
environment: string;
|
|
83
89
|
}>>;
|
|
@@ -87,6 +93,8 @@ export declare function getProject(projectId: string): Promise<ApiResponse<{
|
|
|
87
93
|
platform: string;
|
|
88
94
|
environment: string;
|
|
89
95
|
bundle_id: string | null;
|
|
96
|
+
magic_link_redirect_url: string | null;
|
|
97
|
+
auth_email_brand_name: string | null;
|
|
90
98
|
created_at: string;
|
|
91
99
|
}>>;
|
|
92
100
|
export declare function deleteProject(projectId: string): Promise<ApiResponse<{
|
|
@@ -674,7 +682,7 @@ export declare function dropCollection(projectId: string, name: string, confirm:
|
|
|
674
682
|
deleted: boolean;
|
|
675
683
|
version: number;
|
|
676
684
|
}>>;
|
|
677
|
-
export type AiProviderName = 'anthropic' | 'openai';
|
|
685
|
+
export type AiProviderName = 'anthropic' | 'openai' | 'mistral' | 'gemini';
|
|
678
686
|
export interface AiProviderRow {
|
|
679
687
|
name: AiProviderName;
|
|
680
688
|
/** Whether an API key is currently configured for this provider. */
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { updateProject } from '../api-client.js';
|
|
1
2
|
export declare function projectsListCommand(): Promise<void>;
|
|
2
3
|
export declare function projectsCreateCommand(input: {
|
|
3
4
|
name: string;
|
|
@@ -6,13 +7,19 @@ export declare function projectsCreateCommand(input: {
|
|
|
6
7
|
googleOauthClientId?: string;
|
|
7
8
|
platform?: string;
|
|
8
9
|
}): Promise<void>;
|
|
9
|
-
export
|
|
10
|
+
export interface ProjectUpdateCommandInput {
|
|
10
11
|
name?: string;
|
|
11
12
|
bundleId?: string;
|
|
12
13
|
googleOauthClientId?: string;
|
|
14
|
+
magicLinkRedirectUrl?: string;
|
|
15
|
+
authEmailBrandName?: string;
|
|
16
|
+
clearMagicLinkRedirectUrl?: boolean;
|
|
17
|
+
clearAuthEmailBrandName?: boolean;
|
|
13
18
|
platform?: string;
|
|
14
19
|
environment?: string;
|
|
15
|
-
}
|
|
20
|
+
}
|
|
21
|
+
export declare function buildProjectUpdatePatch(input: ProjectUpdateCommandInput): Parameters<typeof updateProject>[1];
|
|
22
|
+
export declare function projectsUpdateCommand(projectId: string, input: ProjectUpdateCommandInput): Promise<void>;
|
|
16
23
|
export declare function projectsShowCommand(projectId: string): Promise<void>;
|
|
17
24
|
export declare function projectsDeleteCommand(projectId: string, opts?: {
|
|
18
25
|
yes?: boolean;
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { Command } from "commander";
|
|
2
|
+
import { Command, Option } from "commander";
|
|
3
3
|
import pc from "picocolors";
|
|
4
4
|
import { access, chmod, mkdir, mkdtemp, readFile, readdir, rename, rm, stat, writeFile } from "node:fs/promises";
|
|
5
5
|
import { homedir, tmpdir } from "node:os";
|
|
@@ -4738,22 +4738,34 @@ async function projectsCreateCommand(input) {
|
|
|
4738
4738
|
handleError$2(err);
|
|
4739
4739
|
}
|
|
4740
4740
|
}
|
|
4741
|
-
|
|
4742
|
-
|
|
4743
|
-
|
|
4744
|
-
console.log(pc.dim(" ─────────────────────────────────"));
|
|
4745
|
-
console.log();
|
|
4741
|
+
function buildProjectUpdatePatch(input) {
|
|
4742
|
+
if (input.magicLinkRedirectUrl !== void 0 && input.clearMagicLinkRedirectUrl) throw new Error("--magic-link-redirect-url conflicts with --clear-magic-link-redirect-url");
|
|
4743
|
+
if (input.authEmailBrandName !== void 0 && input.clearAuthEmailBrandName) throw new Error("--auth-email-brand-name conflicts with --clear-auth-email-brand-name");
|
|
4746
4744
|
const patch = {};
|
|
4747
4745
|
if (input.name !== void 0) patch.name = input.name;
|
|
4748
4746
|
if (input.bundleId !== void 0) patch.bundle_id = input.bundleId;
|
|
4749
4747
|
if (input.googleOauthClientId !== void 0) patch.google_oauth_client_id = input.googleOauthClientId;
|
|
4750
4748
|
if (input.platform !== void 0) patch.platform = input.platform;
|
|
4751
4749
|
if (input.environment !== void 0) patch.environment = input.environment;
|
|
4750
|
+
if (input.magicLinkRedirectUrl !== void 0) patch.magic_link_redirect_url = input.magicLinkRedirectUrl;
|
|
4751
|
+
if (input.clearMagicLinkRedirectUrl) patch.magic_link_redirect_url = null;
|
|
4752
|
+
if (input.authEmailBrandName !== void 0) patch.auth_email_brand_name = input.authEmailBrandName;
|
|
4753
|
+
if (input.clearAuthEmailBrandName) patch.auth_email_brand_name = null;
|
|
4754
|
+
return patch;
|
|
4755
|
+
}
|
|
4756
|
+
async function projectsUpdateCommand(projectId, input) {
|
|
4757
|
+
console.log();
|
|
4758
|
+
console.log(pc.bold(` amba projects update ${projectId}`));
|
|
4759
|
+
console.log(pc.dim(" ─────────────────────────────────"));
|
|
4760
|
+
console.log();
|
|
4761
|
+
const patch = buildProjectUpdatePatch(input);
|
|
4752
4762
|
try {
|
|
4753
4763
|
const res = await updateProject(projectId, patch);
|
|
4754
4764
|
console.log(pc.green(" ✓") + ` Updated ${pc.bold(res.data.name)} ${pc.dim(`(${res.data.id})`)}`);
|
|
4755
4765
|
if (res.data.bundle_id) console.log(pc.dim(` Bundle ID: ${res.data.bundle_id}`));
|
|
4756
4766
|
if (res.data.google_oauth_client_id) console.log(pc.dim(` Google OAuth client id: ${res.data.google_oauth_client_id}`));
|
|
4767
|
+
if (res.data.magic_link_redirect_url) console.log(pc.dim(` Magic-link callback: ${res.data.magic_link_redirect_url}`));
|
|
4768
|
+
if (res.data.auth_email_brand_name) console.log(pc.dim(` Auth email brand: ${res.data.auth_email_brand_name}`));
|
|
4757
4769
|
console.log();
|
|
4758
4770
|
} catch (err) {
|
|
4759
4771
|
if (err instanceof ApiClientError && err.statusCode === 404) {
|
|
@@ -6602,7 +6614,12 @@ async function functionDomainsRemoveCommand(functionName, hostnameInput) {
|
|
|
6602
6614
|
* server-side; the CLI never echoes plaintext back. The API returns a
|
|
6603
6615
|
* `api_key_preview` (first-6 + last-4) for confirmation.
|
|
6604
6616
|
*/
|
|
6605
|
-
const VALID_PROVIDERS = new Set([
|
|
6617
|
+
const VALID_PROVIDERS = new Set([
|
|
6618
|
+
"anthropic",
|
|
6619
|
+
"openai",
|
|
6620
|
+
"mistral",
|
|
6621
|
+
"gemini"
|
|
6622
|
+
]);
|
|
6606
6623
|
function assertValidProvider(name) {
|
|
6607
6624
|
if (!VALID_PROVIDERS.has(name)) throw new Error(`Unknown AI provider '${name}'. Supported: ${[...VALID_PROVIDERS].join(", ")}.`);
|
|
6608
6625
|
}
|
|
@@ -9761,7 +9778,7 @@ async function diffConfigCommand(file = DEFAULT_BUNDLE_FILE, options = {}) {
|
|
|
9761
9778
|
//#endregion
|
|
9762
9779
|
//#region src/index.ts
|
|
9763
9780
|
const program = new Command();
|
|
9764
|
-
program.name("amba").description("amba — agent-native backend-as-a-service for mobile apps.").version("4.1.
|
|
9781
|
+
program.name("amba").description("amba — agent-native backend-as-a-service for mobile apps.").version("4.1.6");
|
|
9765
9782
|
program.option("--token <pat>", "Use a Personal Access Token for headless / CI / agent use (overrides ~/.amba/credentials.json + AMBA_PAT env)");
|
|
9766
9783
|
program.hook("preAction", (thisCommand) => {
|
|
9767
9784
|
setBearerOverride(resolveTokenSource({
|
|
@@ -9850,13 +9867,17 @@ projects.command("create").description("Create a new project").requiredOption("-
|
|
|
9850
9867
|
platform: opts.platform
|
|
9851
9868
|
}));
|
|
9852
9869
|
});
|
|
9853
|
-
projects.command("update <projectId>").description("Update mutable fields on a project").option("--name <name>", "Display name").option("--bundle-id <id>", "Bundle identifier (Apple Sign In audience)").option("--google-oauth-client-id <id>", "Google OAuth 2.0 client id (Google Sign In audience). Public identifier, not a secret.").option("--platform <platform>", "Platform: 'ios' | 'android' | 'all'").option("--environment <env>", "Environment label: 'development' | 'production'").action(async (projectId, opts) => {
|
|
9870
|
+
projects.command("update <projectId>").description("Update mutable fields on a project").option("--name <name>", "Display name").option("--bundle-id <id>", "Bundle identifier (Apple Sign In audience)").option("--google-oauth-client-id <id>", "Google OAuth 2.0 client id (Google Sign In audience). Public identifier, not a secret.").option("--platform <platform>", "Platform: 'ios' | 'android' | 'all'").option("--environment <env>", "Environment label: 'development' | 'production'").addOption(new Option("--magic-link-redirect-url <url>", "Exact HTTPS callback URL for magic-link sign-in (Amba appends the token query parameter)").conflicts("clearMagicLinkRedirectUrl")).addOption(new Option("--clear-magic-link-redirect-url", "Clear the project callback and restore the platform fallback").conflicts("magicLinkRedirectUrl")).addOption(new Option("--auth-email-brand-name <name>", "Brand shown in auth emails and sender attribution").conflicts("clearAuthEmailBrandName")).addOption(new Option("--clear-auth-email-brand-name", "Clear the auth-email brand and fall back to the project name").conflicts("authEmailBrandName")).action(async (projectId, opts) => {
|
|
9854
9871
|
await runAction(() => projectsUpdateCommand(projectId, {
|
|
9855
9872
|
name: opts.name,
|
|
9856
9873
|
bundleId: opts.bundleId,
|
|
9857
9874
|
googleOauthClientId: opts.googleOauthClientId,
|
|
9858
9875
|
platform: opts.platform,
|
|
9859
|
-
environment: opts.environment
|
|
9876
|
+
environment: opts.environment,
|
|
9877
|
+
magicLinkRedirectUrl: opts.magicLinkRedirectUrl,
|
|
9878
|
+
authEmailBrandName: opts.authEmailBrandName,
|
|
9879
|
+
clearMagicLinkRedirectUrl: opts.clearMagicLinkRedirectUrl,
|
|
9880
|
+
clearAuthEmailBrandName: opts.clearAuthEmailBrandName
|
|
9860
9881
|
}));
|
|
9861
9882
|
});
|
|
9862
9883
|
projects.command("show <projectId>").description("Show full project details as JSON").action(async (projectId) => {
|
|
@@ -10156,7 +10177,7 @@ domains.command("buy <domain>").description("Buy a domain + connect it to a site
|
|
|
10156
10177
|
domains.command("list").description("List domains this project has purchased through Amba").action(async () => {
|
|
10157
10178
|
await runAction(domainsListCommand);
|
|
10158
10179
|
});
|
|
10159
|
-
const aiProviders = program.command("ai").description("AI gateway — manage provider keys + prompts").command("providers").description("Per-project provider key registration (Anthropic, OpenAI)");
|
|
10180
|
+
const aiProviders = program.command("ai").description("AI gateway — manage provider keys + prompts").command("providers").description("Per-project provider key registration (Anthropic, OpenAI, Mistral, Gemini)");
|
|
10160
10181
|
aiProviders.command("add <provider>").description("Register an AI provider key. Plaintext stored securely server-side; a preview (first-6+last-4) is printed back. Use --from-stdin to keep the key out of shell history.").option("--key <value>", "Provider API key plaintext (alternative: --from-stdin)").option("--from-stdin", "Read the key from stdin instead of --key").action(async (provider, opts) => {
|
|
10161
10182
|
await runAction(() => aiProvidersAddCommand(provider, opts));
|
|
10162
10183
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@layers/amba",
|
|
3
|
-
"version": "4.1.
|
|
3
|
+
"version": "4.1.6",
|
|
4
4
|
"description": "amba — agent-native backend-as-a-service. Functions, collections, storage, AI, email, queues, sites, and `amba ship` to take an Expo app live on the App Store + Google Play. `npx @layers/amba init` to start.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -49,8 +49,8 @@
|
|
|
49
49
|
"tsdown": "^0.12.5",
|
|
50
50
|
"typescript": "^5.8.3",
|
|
51
51
|
"vitest": "^3.2.4",
|
|
52
|
-
"@layers/amba-mcp": "4.0.
|
|
53
|
-
"@layers/amba-shared": "4.0.
|
|
52
|
+
"@layers/amba-mcp": "4.0.10",
|
|
53
|
+
"@layers/amba-shared": "4.0.5"
|
|
54
54
|
},
|
|
55
55
|
"scripts": {
|
|
56
56
|
"build": "tsdown && tsc --emitDeclarationOnly",
|
|
@@ -9,8 +9,8 @@ There is no separate "identity provisioning" step — `auth` is the default surf
|
|
|
9
9
|
| Tool | Purpose | Example args |
|
|
10
10
|
| --- | --- | --- |
|
|
11
11
|
| `amba_developer_me` | Verify the developer PAT and read the developer's profile. Pre-flight check before any provisioning. | `{}` |
|
|
12
|
-
| `amba_projects_get` | Read a project's config (
|
|
13
|
-
| `amba_projects_update` | Set
|
|
12
|
+
| `amba_projects_get` | Read a project's config (social audiences, magic-link callback, auth-email brand, platform). | `{ project_id: "p_…" }` |
|
|
13
|
+
| `amba_projects_update` | Set social audiences plus the exact magic-link callback and auth-email brand. Pass null for an auth field to restore its fallback. | `{ project_id, magic_link_redirect_url: "https://app.example.com/auth/callback", auth_email_brand_name: "My App" }` |
|
|
14
14
|
| `amba_users_list` | Browse end-users (app_users) of the project — useful as a smoke check after the first sign-in. | `{ project_id, limit: 20 }` |
|
|
15
15
|
| `amba_users_get` | Fetch a single app_user by id. | `{ project_id, user_id }` |
|
|
16
16
|
| `amba_users_bulk_update` | Set custom properties on many users at once (e.g. backfilling a `tier` property used for segmentation). | `{ project_id, user_ids: [...], properties: { tier: "trial" } }` |
|
|
@@ -18,7 +18,7 @@ There is no separate "identity provisioning" step — `auth` is the default surf
|
|
|
18
18
|
| `amba_delete_api_key` / `amba_api_keys_delete` | Revoke a leaked key. | `{ project_id, api_key_id }` |
|
|
19
19
|
| `amba_assign_role` / `amba_roles_assign` | Grant an RBAC role to an app_user (admin / moderator / etc.). | `{ project_id, user_id, role_id }` |
|
|
20
20
|
|
|
21
|
-
There's no `amba_auth_*` namespace — auth is owned by the SDK on the client side
|
|
21
|
+
There's no `amba_auth_*` namespace — auth is owned by the SDK on the client side. Project-level routing, branding, and social audience configuration use `amba_projects_update`. If the user wants Apple/Google sign-in, the **mandatory** preflight is:
|
|
22
22
|
|
|
23
23
|
```
|
|
24
24
|
mcp__amba__amba_projects_update({
|
|
@@ -30,6 +30,18 @@ mcp__amba__amba_projects_update({
|
|
|
30
30
|
|
|
31
31
|
Without this, the server rejects identity tokens with `AUDIENCE_NOT_CONFIGURED` and the user thinks Amba is broken. If they don't know their bundle id, ask; if they don't have a Google OAuth client yet, tell them to create one at console.cloud.google.com and link it later.
|
|
32
32
|
|
|
33
|
+
For magic-link sign-in, configure the exact HTTPS callback before sending a production email:
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
mcp__amba__amba_projects_update({
|
|
37
|
+
project_id: process.env.AMBA_PROJECT_ID,
|
|
38
|
+
magic_link_redirect_url: "https://app.example.com/auth/callback",
|
|
39
|
+
auth_email_brand_name: "Example App"
|
|
40
|
+
})
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Amba appends the one-time `token` query parameter to that exact URL. Auth-email copy uses the project brand; sends from the shared platform mailbox retain visible `via Amba` attribution. A pure customer-branded From address requires a separately verified sender domain.
|
|
44
|
+
|
|
33
45
|
## SDK init per stack
|
|
34
46
|
|
|
35
47
|
### Expo
|