@cardelli/ambit 0.2.3 → 0.3.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/README.md +38 -22
- package/esm/cli/commands/create/index.js +53 -17
- package/esm/cli/commands/create/machine.d.ts +2 -1
- package/esm/cli/commands/create/machine.d.ts.map +1 -1
- package/esm/cli/commands/create/machine.js +70 -29
- package/esm/cli/commands/deploy/index.js +2 -4
- package/esm/cli/commands/deploy/machine.d.ts.map +1 -1
- package/esm/cli/commands/destroy/app.d.ts.map +1 -1
- package/esm/cli/commands/destroy/index.js +2 -0
- package/esm/cli/commands/destroy/network.d.ts.map +1 -1
- package/esm/cli/commands/destroy/network.js +66 -5
- package/esm/cli/commands/doctor.js +13 -4
- package/esm/cli/commands/list.js +1 -1
- package/esm/cli/commands/share.d.ts +2 -0
- package/esm/cli/commands/share.d.ts.map +1 -0
- package/esm/cli/commands/share.js +250 -0
- package/esm/cli/commands/status.js +4 -1
- package/esm/cli/mod.d.ts.map +1 -1
- package/esm/cli/mod.js +2 -0
- package/esm/deno.js +1 -1
- package/esm/lib/command.d.ts.map +1 -1
- package/esm/lib/command.js +5 -7
- package/esm/main.d.ts +1 -0
- package/esm/main.d.ts.map +1 -1
- package/esm/main.js +2 -0
- package/esm/providers/fly.d.ts.map +1 -1
- package/esm/providers/fly.js +14 -3
- package/esm/providers/tailscale.d.ts +7 -0
- package/esm/providers/tailscale.d.ts.map +1 -1
- package/esm/providers/tailscale.js +23 -1
- package/esm/router/start.sh +7 -4
- package/esm/util/constants.d.ts +0 -1
- package/esm/util/constants.d.ts.map +1 -1
- package/esm/util/constants.js +0 -1
- package/esm/util/credentials.d.ts.map +1 -1
- package/esm/util/credentials.js +1 -1
- package/esm/util/discovery.d.ts.map +1 -1
- package/esm/util/discovery.js +1 -1
- package/esm/util/tailscale-local.d.ts +41 -0
- package/esm/util/tailscale-local.d.ts.map +1 -1
- package/esm/util/tailscale-local.js +146 -0
- package/esm/util/template.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -8,6 +8,47 @@ export declare const isAcceptRoutesEnabled: () => Promise<boolean>;
|
|
|
8
8
|
*/
|
|
9
9
|
export declare const enableAcceptRoutes: () => Promise<boolean>;
|
|
10
10
|
export declare const waitForDevice: (provider: TailscaleProvider, hostname: string, timeoutMs?: number) => Promise<TailscaleDevice>;
|
|
11
|
+
/**
|
|
12
|
+
* Asserts that a patch operation only added data and never removed any
|
|
13
|
+
* top-level key or shortened any existing array. Throws if the invariant is
|
|
14
|
+
* violated so callers can surface a hard error before writing to the API.
|
|
15
|
+
*/
|
|
16
|
+
export declare const assertAdditivePatch: (original: Record<string, unknown>, patched: Record<string, unknown>) => void;
|
|
11
17
|
export declare const isTagOwnerConfigured: (policy: Record<string, unknown> | null, tag: string) => boolean;
|
|
12
18
|
export declare const isAutoApproverConfigured: (policy: Record<string, unknown> | null, tag: string) => boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Returns a new policy with the given tag added to tagOwners.
|
|
21
|
+
* No-op if the tag is already present.
|
|
22
|
+
*/
|
|
23
|
+
export declare const patchTagOwner: (policy: Record<string, unknown>, tag: string, owners?: string[]) => Record<string, unknown>;
|
|
24
|
+
/**
|
|
25
|
+
* Returns a new policy with the given route + tag added to autoApprovers.
|
|
26
|
+
* No-op if the tag is already an approver for any route.
|
|
27
|
+
*/
|
|
28
|
+
export declare const patchAutoApprover: (policy: Record<string, unknown>, tag: string, route: string) => Record<string, unknown>;
|
|
29
|
+
/**
|
|
30
|
+
* Returns true if there is already an accept rule where `src` contains the
|
|
31
|
+
* given source member and `dst` contains the given destination.
|
|
32
|
+
*/
|
|
33
|
+
export declare const isAclRuleConfigured: (policy: Record<string, unknown> | null, src: string, dst: string) => boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Returns a new policy with an accept rule `src → dst` appended to `acls`.
|
|
36
|
+
* No-op if an identical rule already exists.
|
|
37
|
+
*/
|
|
38
|
+
export declare const patchAclRule: (policy: Record<string, unknown>, src: string, dst: string) => Record<string, unknown>;
|
|
39
|
+
/**
|
|
40
|
+
* Returns a new policy with all accept rules matching `src → dst` removed from `acls`.
|
|
41
|
+
* No-op if no such rule exists.
|
|
42
|
+
*/
|
|
43
|
+
export declare const unpatchAclRule: (policy: Record<string, unknown>, src: string, dst: string) => Record<string, unknown>;
|
|
44
|
+
/**
|
|
45
|
+
* Returns a new policy with the given tag removed from tagOwners.
|
|
46
|
+
* No-op if the tag is not present.
|
|
47
|
+
*/
|
|
48
|
+
export declare const unpatchTagOwner: (policy: Record<string, unknown>, tag: string) => Record<string, unknown>;
|
|
49
|
+
/**
|
|
50
|
+
* Returns a new policy with the given tag removed from all autoApprovers routes.
|
|
51
|
+
* If a route's approver list becomes empty after removal, the route entry is dropped.
|
|
52
|
+
*/
|
|
53
|
+
export declare const unpatchAutoApprover: (policy: Record<string, unknown>, tag: string) => Record<string, unknown>;
|
|
13
54
|
//# sourceMappingURL=tailscale-local.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tailscale-local.d.ts","sourceRoot":"","sources":["../../src/util/tailscale-local.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAMnE,eAAO,MAAM,oBAAoB,QAAa,OAAO,CAAC,OAAO,CAE5D,CAAC;AAEF,eAAO,MAAM,qBAAqB,QAAa,OAAO,CAAC,OAAO,CAM7D,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,kBAAkB,QAAa,OAAO,CAAC,OAAO,CAG1D,CAAC;AAMF,eAAO,MAAM,aAAa,GACxB,UAAU,iBAAiB,EAC3B,UAAU,MAAM,EAChB,YAAW,MAAe,KACzB,OAAO,CAAC,eAAe,CAazB,CAAC;AAMF,eAAO,MAAM,oBAAoB,GAC/B,QAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,EACtC,KAAK,MAAM,KACV,OASF,CAAC;AAEF,eAAO,MAAM,wBAAwB,GACnC,QAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,EACtC,KAAK,MAAM,KACV,OAgBF,CAAC"}
|
|
1
|
+
{"version":3,"file":"tailscale-local.d.ts","sourceRoot":"","sources":["../../src/util/tailscale-local.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAMnE,eAAO,MAAM,oBAAoB,QAAa,OAAO,CAAC,OAAO,CAE5D,CAAC;AAEF,eAAO,MAAM,qBAAqB,QAAa,OAAO,CAAC,OAAO,CAM7D,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,kBAAkB,QAAa,OAAO,CAAC,OAAO,CAG1D,CAAC;AAMF,eAAO,MAAM,aAAa,GACxB,UAAU,iBAAiB,EAC3B,UAAU,MAAM,EAChB,YAAW,MAAe,KACzB,OAAO,CAAC,eAAe,CAazB,CAAC;AAMF;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,GAC9B,UAAU,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC/B,IAiBF,CAAC;AAMF,eAAO,MAAM,oBAAoB,GAC/B,QAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,EACtC,KAAK,MAAM,KACV,OASF,CAAC;AAEF,eAAO,MAAM,wBAAwB,GACnC,QAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,EACtC,KAAK,MAAM,KACV,OAgBF,CAAC;AAMF;;;GAGG;AACH,eAAO,MAAM,aAAa,GACxB,QAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,KAAK,MAAM,EACX,SAAQ,MAAM,EAAwB,KACrC,MAAM,CAAC,MAAM,EAAE,OAAO,CAIxB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,iBAAiB,GAC5B,QAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,KAAK,MAAM,EACX,OAAO,MAAM,KACZ,MAAM,CAAC,MAAM,EAAE,OAAO,CAYxB,CAAC;AAaF;;;GAGG;AACH,eAAO,MAAM,mBAAmB,GAC9B,QAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,EACtC,KAAK,MAAM,EACX,KAAK,MAAM,KACV,OAUF,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,YAAY,GACvB,QAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,KAAK,MAAM,EACX,KAAK,MAAM,KACV,MAAM,CAAC,MAAM,EAAE,OAAO,CAOxB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,cAAc,GACzB,QAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,KAAK,MAAM,EACX,KAAK,MAAM,KACV,MAAM,CAAC,MAAM,EAAE,OAAO,CAaxB,CAAC;AAMF;;;GAGG;AACH,eAAO,MAAM,eAAe,GAC1B,QAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,KAAK,MAAM,KACV,MAAM,CAAC,MAAM,EAAE,OAAO,CAQxB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,mBAAmB,GAC9B,QAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,KAAK,MAAM,KACV,MAAM,CAAC,MAAM,EAAE,OAAO,CA+BxB,CAAC"}
|
|
@@ -40,6 +40,28 @@ export const waitForDevice = async (provider, hostname, timeoutMs = 120000) => {
|
|
|
40
40
|
return die(`Timeout Waiting for Device '${hostname}'`);
|
|
41
41
|
};
|
|
42
42
|
// =============================================================================
|
|
43
|
+
// Sanity Guards
|
|
44
|
+
// =============================================================================
|
|
45
|
+
/**
|
|
46
|
+
* Asserts that a patch operation only added data and never removed any
|
|
47
|
+
* top-level key or shortened any existing array. Throws if the invariant is
|
|
48
|
+
* violated so callers can surface a hard error before writing to the API.
|
|
49
|
+
*/
|
|
50
|
+
export const assertAdditivePatch = (original, patched) => {
|
|
51
|
+
for (const key of Object.keys(original)) {
|
|
52
|
+
if (!(key in patched)) {
|
|
53
|
+
throw new Error(`ACL sanity check failed: key '${key}' was unexpectedly removed`);
|
|
54
|
+
}
|
|
55
|
+
const origVal = original[key];
|
|
56
|
+
const patchedVal = patched[key];
|
|
57
|
+
if (Array.isArray(origVal) && Array.isArray(patchedVal)) {
|
|
58
|
+
if (patchedVal.length < origVal.length) {
|
|
59
|
+
throw new Error(`ACL sanity check failed: '${key}' array shrank (${origVal.length} → ${patchedVal.length} entries)`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
// =============================================================================
|
|
43
65
|
// Pure Policy Checks
|
|
44
66
|
// =============================================================================
|
|
45
67
|
export const isTagOwnerConfigured = (policy, tag) => {
|
|
@@ -61,3 +83,127 @@ export const isAutoApproverConfigured = (policy, tag) => {
|
|
|
61
83
|
return false;
|
|
62
84
|
return Object.values(routes).some((approvers) => Array.isArray(approvers) && approvers.includes(tag));
|
|
63
85
|
};
|
|
86
|
+
// =============================================================================
|
|
87
|
+
// ACL Policy Patching (Pure)
|
|
88
|
+
// =============================================================================
|
|
89
|
+
/**
|
|
90
|
+
* Returns a new policy with the given tag added to tagOwners.
|
|
91
|
+
* No-op if the tag is already present.
|
|
92
|
+
*/
|
|
93
|
+
export const patchTagOwner = (policy, tag, owners = ["autogroup:admin"]) => {
|
|
94
|
+
const tagOwners = (policy.tagOwners ?? {});
|
|
95
|
+
if (tag in tagOwners)
|
|
96
|
+
return policy;
|
|
97
|
+
return { ...policy, tagOwners: { ...tagOwners, [tag]: owners } };
|
|
98
|
+
};
|
|
99
|
+
/**
|
|
100
|
+
* Returns a new policy with the given route + tag added to autoApprovers.
|
|
101
|
+
* No-op if the tag is already an approver for any route.
|
|
102
|
+
*/
|
|
103
|
+
export const patchAutoApprover = (policy, tag, route) => {
|
|
104
|
+
const autoApprovers = (policy.autoApprovers ?? {});
|
|
105
|
+
const routes = (autoApprovers.routes ?? {});
|
|
106
|
+
const existing = routes[route] ?? [];
|
|
107
|
+
if (existing.includes(tag))
|
|
108
|
+
return policy;
|
|
109
|
+
return {
|
|
110
|
+
...policy,
|
|
111
|
+
autoApprovers: {
|
|
112
|
+
...autoApprovers,
|
|
113
|
+
routes: { ...routes, [route]: [...existing, tag] },
|
|
114
|
+
},
|
|
115
|
+
};
|
|
116
|
+
};
|
|
117
|
+
/**
|
|
118
|
+
* Returns true if there is already an accept rule where `src` contains the
|
|
119
|
+
* given source member and `dst` contains the given destination.
|
|
120
|
+
*/
|
|
121
|
+
export const isAclRuleConfigured = (policy, src, dst) => {
|
|
122
|
+
if (!policy)
|
|
123
|
+
return false;
|
|
124
|
+
const acls = policy.acls;
|
|
125
|
+
if (!Array.isArray(acls))
|
|
126
|
+
return false;
|
|
127
|
+
return acls.some((rule) => rule.action === "accept" &&
|
|
128
|
+
Array.isArray(rule.src) && rule.src.includes(src) &&
|
|
129
|
+
Array.isArray(rule.dst) && rule.dst.includes(dst));
|
|
130
|
+
};
|
|
131
|
+
/**
|
|
132
|
+
* Returns a new policy with an accept rule `src → dst` appended to `acls`.
|
|
133
|
+
* No-op if an identical rule already exists.
|
|
134
|
+
*/
|
|
135
|
+
export const patchAclRule = (policy, src, dst) => {
|
|
136
|
+
if (isAclRuleConfigured(policy, src, dst))
|
|
137
|
+
return policy;
|
|
138
|
+
const acls = (policy.acls ?? []);
|
|
139
|
+
return {
|
|
140
|
+
...policy,
|
|
141
|
+
acls: [...acls, { action: "accept", src: [src], dst: [dst] }],
|
|
142
|
+
};
|
|
143
|
+
};
|
|
144
|
+
/**
|
|
145
|
+
* Returns a new policy with all accept rules matching `src → dst` removed from `acls`.
|
|
146
|
+
* No-op if no such rule exists.
|
|
147
|
+
*/
|
|
148
|
+
export const unpatchAclRule = (policy, src, dst) => {
|
|
149
|
+
const acls = policy.acls;
|
|
150
|
+
if (!Array.isArray(acls))
|
|
151
|
+
return policy;
|
|
152
|
+
const filtered = acls.filter((rule) => !(rule.action === "accept" &&
|
|
153
|
+
Array.isArray(rule.src) && rule.src.includes(src) &&
|
|
154
|
+
Array.isArray(rule.dst) && rule.dst.includes(dst)));
|
|
155
|
+
if (filtered.length === acls.length)
|
|
156
|
+
return policy;
|
|
157
|
+
return { ...policy, acls: filtered };
|
|
158
|
+
};
|
|
159
|
+
// =============================================================================
|
|
160
|
+
// ACL Policy Un-patching (Pure) — inverse of the patch helpers above
|
|
161
|
+
// =============================================================================
|
|
162
|
+
/**
|
|
163
|
+
* Returns a new policy with the given tag removed from tagOwners.
|
|
164
|
+
* No-op if the tag is not present.
|
|
165
|
+
*/
|
|
166
|
+
export const unpatchTagOwner = (policy, tag) => {
|
|
167
|
+
const tagOwners = policy.tagOwners;
|
|
168
|
+
if (!tagOwners || !(tag in tagOwners))
|
|
169
|
+
return policy;
|
|
170
|
+
const { [tag]: _, ...rest } = tagOwners;
|
|
171
|
+
const hasKeys = Object.keys(rest).length > 0;
|
|
172
|
+
return hasKeys
|
|
173
|
+
? { ...policy, tagOwners: rest }
|
|
174
|
+
: { ...policy, tagOwners: {} };
|
|
175
|
+
};
|
|
176
|
+
/**
|
|
177
|
+
* Returns a new policy with the given tag removed from all autoApprovers routes.
|
|
178
|
+
* If a route's approver list becomes empty after removal, the route entry is dropped.
|
|
179
|
+
*/
|
|
180
|
+
export const unpatchAutoApprover = (policy, tag) => {
|
|
181
|
+
const autoApprovers = policy.autoApprovers;
|
|
182
|
+
if (!autoApprovers)
|
|
183
|
+
return policy;
|
|
184
|
+
const routes = autoApprovers.routes;
|
|
185
|
+
if (!routes)
|
|
186
|
+
return policy;
|
|
187
|
+
const cleaned = {};
|
|
188
|
+
let changed = false;
|
|
189
|
+
for (const [route, approvers] of Object.entries(routes)) {
|
|
190
|
+
if (!Array.isArray(approvers)) {
|
|
191
|
+
cleaned[route] = approvers;
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
const filtered = approvers.filter((a) => a !== tag);
|
|
195
|
+
if (filtered.length !== approvers.length)
|
|
196
|
+
changed = true;
|
|
197
|
+
if (filtered.length > 0)
|
|
198
|
+
cleaned[route] = filtered;
|
|
199
|
+
}
|
|
200
|
+
if (!changed)
|
|
201
|
+
return policy;
|
|
202
|
+
return {
|
|
203
|
+
...policy,
|
|
204
|
+
autoApprovers: {
|
|
205
|
+
...autoApprovers,
|
|
206
|
+
routes: cleaned,
|
|
207
|
+
},
|
|
208
|
+
};
|
|
209
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"template.d.ts","sourceRoot":"","sources":["../../src/util/template.ts"],"names":[],"mappings":"AAqBA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAM1C,wCAAwC;AACxC,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;CACzB;AAED,iDAAiD;AACjD,MAAM,MAAM,mBAAmB,GAAG,MAAM,CACtC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CACzC,CAAC;AAyBF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,gBAAgB,GAAI,KAAK,MAAM,KAAG,WAAW,GAAG,IAyB5D,CAAC;AAMF;;;;;;;;;GASG;AACH,eAAO,MAAM,aAAa,GACxB,KAAK,WAAW,KACf,OAAO,CAAC,mBAAmB,
|
|
1
|
+
{"version":3,"file":"template.d.ts","sourceRoot":"","sources":["../../src/util/template.ts"],"names":[],"mappings":"AAqBA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAM1C,wCAAwC;AACxC,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;CACzB;AAED,iDAAiD;AACjD,MAAM,MAAM,mBAAmB,GAAG,MAAM,CACtC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CACzC,CAAC;AAyBF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,gBAAgB,GAAI,KAAK,MAAM,KAAG,WAAW,GAAG,IAyB5D,CAAC;AAMF;;;;;;;;;GASG;AACH,eAAO,MAAM,aAAa,GACxB,KAAK,WAAW,KACf,OAAO,CAAC,mBAAmB,CAuG7B,CAAC"}
|