@dotrino/vault 0.4.0 → 0.5.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 +2 -2
  2. package/src/enroll.js +20 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dotrino/vault",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "Usa ESTE dispositivo (navegador) como bóveda/CA del ecosistema Dotrino: atiende enrolamientos por el proxy y firma certificados de delegación a tus máquinas. Incluye el cliente de SERVICIO (Node): un proyecto se enrola una vez y jala sus credenciales del vault en vez del .env (`import '@dotrino/vault/config'`).",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -42,7 +42,7 @@
42
42
  "pairing"
43
43
  ],
44
44
  "peerDependencies": {
45
- "@dotrino/identity": ">=0.23.0",
45
+ "@dotrino/identity": ">=0.24.0",
46
46
  "@dotrino/proxy-client": ">=0.6.0"
47
47
  },
48
48
  "license": "MIT",
package/src/enroll.js CHANGED
@@ -44,6 +44,11 @@ export const MSG_ENROLLED = 'vault.enrolled'
44
44
  export const MSG_REVOKED = 'vault.revoked'
45
45
  export const MSG_ERROR = 'vault.error'
46
46
 
47
+ /** Los scopes del cert se corresponden 1:1 con las capacidades del acta (§D7). */
48
+ const SCOPE_TO_CAP = { 'vault:sign': 'sign', 'vault:store': 'store', 'vault:read': 'read' }
49
+ export const scopeToCaps = (scope) =>
50
+ (Array.isArray(scope) ? scope : [scope]).map((s) => SCOPE_TO_CAP[s]).filter(Boolean)
51
+
47
52
  /** Token aleatorio de 128 bits en hex. */
48
53
  export function randToken () {
49
54
  const b = crypto.getRandomValues(new Uint8Array(16))
@@ -193,10 +198,24 @@ export function createEnrollDesk ({
193
198
  }
194
199
 
195
200
  const { cert } = await identity.signDelegation(pend.dpub, pend.scope, { ttlMs: pend.ttlMs, label: pend.label })
201
+
202
+ // Aprobar un emparejamiento ES admitir al dispositivo en el perfil: el cert es la
203
+ // credencial y el acta es la política, y no tiene sentido emitir una sin la otra.
204
+ // Las capacidades salen del scope que se pidió al emparejar (cert ∩ acta, §2.3).
205
+ let acta = null
206
+ try {
207
+ if (typeof identity.admitMember === 'function') {
208
+ const caps = scopeToCaps(pend.scope)
209
+ if (caps.length) await identity.admitMember({ pub: pend.dpub, label: pend.label || '', caps, cert })
210
+ }
211
+ acta = (await identity.profileActa?.())?.acta || null
212
+ } catch (e) { log('[vault] no se pudo admitir en el acta:', e.message) }
213
+
196
214
  audit('enroll', { device: pend.deviceId, label: pend.label || '', scope: pend.scope })
197
215
  // Echamos el código tipeado junto al cert: el DISPOSITIVO acepta solo si coincide
198
216
  // con el que generó → una bóveda falsa (que no lo conoce) no puede enrolarlo.
199
- reply(pend.from, { type: MSG_ENROLLED, code, cert, iss })
217
+ // El acta viaja con el cert: el dispositivo ya sabe de quién es el perfil al que entra.
218
+ reply(pend.from, { type: MSG_ENROLLED, code, cert, iss, acta })
200
219
  pend.state = 'DONE'
201
220
  pending.delete(pend.token)
202
221
  fire(onPendingChange)