@fabrika/installation-init 0.3.2 → 0.4.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.
Files changed (2) hide show
  1. package/package.json +3 -3
  2. package/src/admin.ts +7 -13
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fabrika/installation-init",
3
- "version": "0.3.2",
3
+ "version": "0.4.0",
4
4
  "type": "module",
5
5
  "repository": {
6
6
  "type": "git",
@@ -27,7 +27,7 @@
27
27
  },
28
28
  "dependencies": {
29
29
  "zod": "^3.25.76",
30
- "@fabrika/app": "^0.3.2",
31
- "@fabrika/iam-contract": "^0.3.2"
30
+ "@fabrika/app": "^0.4.0",
31
+ "@fabrika/iam-contract": "^0.4.0"
32
32
  }
33
33
  }
package/src/admin.ts CHANGED
@@ -7,14 +7,10 @@
7
7
  * nothing. WHERE an installation's IAM answers, and how an operator names it, is the provider's own
8
8
  * question and stays in its installation package.
9
9
  *
10
- * Two traps a live bring-up found are encoded here rather than left to each caller:
11
- *
12
- * - **The grant is CROSS-APP (`app: null`).** Grants filter to the calling app, so an `admin` grant
13
- * scoped to the console's own app id leaves Delivery and Operations working while the Access plane
14
- * refuses. IAM's own app id is not a registered app, so naming it would dangle instead.
15
- * - **The two admin inputs disagree.** `grants.create` keys on `principalId` while `principals.get`
16
- * and `passwords.issueEnrollment` take `PrincipalIdInput`, which keys on `id` — the obvious call
17
- * answers `400 id: Required`. Hidden here deliberately; harmonizing the surface is its own work.
10
+ * A trap a live bring-up found is encoded here rather than left to each caller: **the grant is
11
+ * CROSS-APP (`app: null`).** Grants filter to the calling app, so an `admin` grant scoped to the
12
+ * console's own app id leaves Delivery and Operations working while the Access plane refuses. IAM's
13
+ * own app id is not a registered app, so naming it would dangle instead.
18
14
  *
19
15
  * The enrollment URL is a CREDENTIAL IN TRANSIT. It is RETURNED, never logged: nothing in this module
20
16
  * prints, and `log.ts` deliberately has no helper that takes a secret value.
@@ -243,13 +239,11 @@ export const ensureFirstAdministrator = async (
243
239
  if (principal.status === 'disabled') {
244
240
  throw new Error(
245
241
  `principal ${principal.id} holds ${email} and is disabled — a disabled principal cannot sign in. Name a different `
246
- + 'mailbox, or re-enable this one with `principals.update` ({ id, disabled: false }) before running this again',
242
+ + 'mailbox, or re-enable this one with `principals.update` ({ principalId, disabled: false }) before running this again',
247
243
  )
248
244
  }
249
245
 
250
- // `principals.get` keys on `id`; `grants.create` below keys on `principalId`. Same principal, two
251
- // spellings — this is the difference the command hides.
252
- const detail = await step('principals.get', () => client.principals.get({ id: principal.id }))
246
+ const detail = await step('principals.get', () => client.principals.get({ principalId: principal.id }))
253
247
  const now = Math.floor(Date.now() / 1000)
254
248
  const granted = detail.grants.some((grant) => isCrossAppAdminGrant(grant, now))
255
249
  if (!granted) {
@@ -293,7 +287,7 @@ const ensureEnrollment = async (
293
287
  if (state === 'pending' && !reissue) {
294
288
  return { state: 'outstanding' }
295
289
  }
296
- const delivery = await step('passwords.issueEnrollment', () => client.passwords.issueEnrollment({ id: principalId }))
290
+ const delivery = await step('passwords.issueEnrollment', () => client.passwords.issueEnrollment({ principalId }))
297
291
  return delivery.delivery === 'manual'
298
292
  ? { state: 'issued', url: delivery.url, expiresAt: delivery.expiresAt }
299
293
  : { state: 'emailed', email: delivery.email, expiresAt: delivery.expiresAt }