@humanagencyp/hap-core 0.11.0 → 0.11.2
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/index.d.mts +56 -1
- package/dist/index.d.ts +56 -1
- package/dist/index.js +35 -0
- package/dist/index.mjs +31 -0
- package/package.json +1 -1
- package/src/commitment-modes.ts +51 -0
- package/src/index.ts +1 -0
- package/src/types.ts +32 -0
package/dist/index.d.mts
CHANGED
|
@@ -315,6 +315,19 @@ interface ProfileBoundsField {
|
|
|
315
315
|
* kinds, and the same boundType can carry different units.
|
|
316
316
|
*/
|
|
317
317
|
unit?: FieldUnit;
|
|
318
|
+
/**
|
|
319
|
+
* The largest value a mandate may set for this (numeric) bound — a ceiling
|
|
320
|
+
* on what the owner can grant, declared by the profile. E.g. reporting@0.2
|
|
321
|
+
* `read_max_age_days: { maximum: 366 }`: no reporting mandate may read back
|
|
322
|
+
* further than a year.
|
|
323
|
+
*
|
|
324
|
+
* Distinct from the bound itself: the bound limits each ACTION; `maximum`
|
|
325
|
+
* limits the MANDATE. A value above it is not a valid mandate for this
|
|
326
|
+
* profile — the mandate editor caps its input, the issuing Authority Server
|
|
327
|
+
* should refuse it, and an enforcement point that reads the bound applies
|
|
328
|
+
* min(value, maximum). Absent → no ceiling.
|
|
329
|
+
*/
|
|
330
|
+
maximum?: number;
|
|
318
331
|
/** @deprecated v0.4: use boundType instead. */
|
|
319
332
|
constraint?: FieldConstraint;
|
|
320
333
|
/** @deprecated v0.4: use boundType: { kind: 'enum', values: [...] }. */
|
|
@@ -467,6 +480,11 @@ interface ExecutionPath {
|
|
|
467
480
|
*
|
|
468
481
|
* Supports both v0.3 (frameSchema) and v0.4 (boundsSchema + contextSchema).
|
|
469
482
|
*/
|
|
483
|
+
/**
|
|
484
|
+
* A commitment mode a person can choose when signing a mandate. (`review_above_cap`
|
|
485
|
+
* is not chosen by the signer — it follows from team caps.)
|
|
486
|
+
*/
|
|
487
|
+
type SignableCommitmentMode = 'automatic' | 'review';
|
|
470
488
|
interface AgentProfile {
|
|
471
489
|
id: string;
|
|
472
490
|
name?: string;
|
|
@@ -508,6 +526,18 @@ interface AgentProfile {
|
|
|
508
526
|
* a forwarded message has usually lost the footer that carried it.
|
|
509
527
|
*/
|
|
510
528
|
receipt_lookup?: boolean;
|
|
529
|
+
/**
|
|
530
|
+
* The commitment modes a mandate under this profile may be signed with.
|
|
531
|
+
* Absent → every mode (`automatic`, `review`), as before this field existed.
|
|
532
|
+
*
|
|
533
|
+
* Lets a profile be review-only: every action it governs then needs a
|
|
534
|
+
* person's approval, whatever the signer would have picked. The Authority
|
|
535
|
+
* Server refuses to sign a mandate whose `commitment_mode` is not listed;
|
|
536
|
+
* a mandate screen offers only the listed modes. Fail-closed: a declared
|
|
537
|
+
* list with no valid entry allows nothing — a malformed declaration never
|
|
538
|
+
* widens what a profile allows. See {@link allowedCommitmentModes}.
|
|
539
|
+
*/
|
|
540
|
+
commitment_modes?: readonly SignableCommitmentMode[];
|
|
511
541
|
/**
|
|
512
542
|
* v0.3 frame schema (deprecated, kept for backward compat).
|
|
513
543
|
* Used when boundsSchema is not present.
|
|
@@ -1081,6 +1111,31 @@ declare function computeBoundsHash(params: AgentBoundsParams, profile: AgentProf
|
|
|
1081
1111
|
*/
|
|
1082
1112
|
declare function computeContextHash(params: AgentContextParams, profile: AgentProfile): string;
|
|
1083
1113
|
|
|
1114
|
+
/**
|
|
1115
|
+
* Which commitment modes a profile allows its mandates to be signed with
|
|
1116
|
+
* (`AgentProfile.commitment_modes`). One source for the Authority Server's
|
|
1117
|
+
* refusal and the mandate screen's choice, so the two cannot disagree.
|
|
1118
|
+
*/
|
|
1119
|
+
|
|
1120
|
+
/** Every mode a signer can choose, in the order a mandate screen shows them. */
|
|
1121
|
+
declare const SIGNABLE_COMMITMENT_MODES: readonly SignableCommitmentMode[];
|
|
1122
|
+
/**
|
|
1123
|
+
* The modes a mandate under this profile may carry, in display order.
|
|
1124
|
+
* No declaration → all of them. A declaration is read fail-closed: entries
|
|
1125
|
+
* that are not a signable mode are dropped, so a malformed list can only
|
|
1126
|
+
* narrow — `[]`, `"review"` (not a list) or `["reveiw"]` allow nothing.
|
|
1127
|
+
*/
|
|
1128
|
+
declare function allowedCommitmentModes(profile: AgentProfile): readonly SignableCommitmentMode[];
|
|
1129
|
+
/** Whether a mandate under this profile may be signed with `mode`. */
|
|
1130
|
+
declare function isCommitmentModeAllowed(profile: AgentProfile, mode: string): boolean;
|
|
1131
|
+
/**
|
|
1132
|
+
* Authoring check for a profile's `commitment_modes` declaration — for
|
|
1133
|
+
* hap-profiles CI, an authoring tool or a test. Like `validateBoundsRequiredFor`
|
|
1134
|
+
* it is not wired into profile loading; enforcement reads the declaration
|
|
1135
|
+
* fail-closed through `allowedCommitmentModes`. Empty array = nothing to fix.
|
|
1136
|
+
*/
|
|
1137
|
+
declare function validateCommitmentModes(profile: AgentProfile): string[];
|
|
1138
|
+
|
|
1084
1139
|
/**
|
|
1085
1140
|
* Attestation Encoding, Decoding, and Verification
|
|
1086
1141
|
*
|
|
@@ -1401,4 +1456,4 @@ interface ReceiptPayload {
|
|
|
1401
1456
|
*/
|
|
1402
1457
|
declare function verifyReceiptSignature(receipt: ReceiptPayload, publicKeyHex: string): Promise<void>;
|
|
1403
1458
|
|
|
1404
|
-
export { type AgentBoundsParams, type AgentContextParams, type AgentFrameParams, type AgentProfile, type ApprovalObject, type Attestation, type AttestationHeader, type AttestationPayload, type BoundType, CanonicalValueError, type ContentBinding, ContentBindingError, type ContentBindingErrorCode, type CumulativeFieldDef, type CumulativeWindow, type DeclaredFieldDef, type ExecutionContextFieldDef, type ExecutionLogEntry, type ExecutionLogQuery, type ExecutionMappingTransform, type ExecutionMappingValue, type ExecutionPath, type FieldConstraint, type FieldUnit, type GateQuestion, type GatekeeperError, type GatekeeperRequest, type GatekeeperResult, type MandateBinding, MandateError, type MandateProjection, type OwnerMandate, type ProfileBoundsField, type ProfileContextField, type ProfileFrameField, type ProfileToolGating, type ProfileToolGatingEntry, type ReceiptPayload, type ResolvedDomain, type SigningSurface, type Subject, type SubjectValidation, approvalSigningBytes, attestationId, bindingAppliesTo, boundActionTypes, buildMandateProjection, canonicalBounds, canonicalContext, canonicalFrame, canonicalize, canonicalizeText, checkAttestationExpiry, clearProfiles, computeBoundsHash, computeContentHash, computeContextHash, computeFieldsContentHash, computeFrameHash, computeIntentDisclosureHash, computeIntentHash, contentCanonicalBytes, decodeAttestationBlob, decodeDidKey, deriveIdentityLine, encodeAttestationBlob, encodeDidKey, frameHash, getAllProfiles, getProfile, intentDisclosureCanonicalBytes, isFieldBinding, isKeyBearingDid, isV4Attestation, listProfiles, mandateSigningBytes, registerProfile, selectBoundFields, signApproval, signMandateProjection, validateBoundsParams, validateBoundsRequiredFor, validateContextParams, validateFrameParams, validateSubject, verify, verifyApproval, verifyAttestation, verifyAttestationSignature, verifyAttestationV4, verifyBoundsHash, verifyContextHash, verifyFrameHash, verifyOwnerMandate, verifyOwnerMandates, verifyReceiptSignature };
|
|
1459
|
+
export { type AgentBoundsParams, type AgentContextParams, type AgentFrameParams, type AgentProfile, type ApprovalObject, type Attestation, type AttestationHeader, type AttestationPayload, type BoundType, CanonicalValueError, type ContentBinding, ContentBindingError, type ContentBindingErrorCode, type CumulativeFieldDef, type CumulativeWindow, type DeclaredFieldDef, type ExecutionContextFieldDef, type ExecutionLogEntry, type ExecutionLogQuery, type ExecutionMappingTransform, type ExecutionMappingValue, type ExecutionPath, type FieldConstraint, type FieldUnit, type GateQuestion, type GatekeeperError, type GatekeeperRequest, type GatekeeperResult, type MandateBinding, MandateError, type MandateProjection, type OwnerMandate, type ProfileBoundsField, type ProfileContextField, type ProfileFrameField, type ProfileToolGating, type ProfileToolGatingEntry, type ReceiptPayload, type ResolvedDomain, SIGNABLE_COMMITMENT_MODES, type SignableCommitmentMode, type SigningSurface, type Subject, type SubjectValidation, allowedCommitmentModes, approvalSigningBytes, attestationId, bindingAppliesTo, boundActionTypes, buildMandateProjection, canonicalBounds, canonicalContext, canonicalFrame, canonicalize, canonicalizeText, checkAttestationExpiry, clearProfiles, computeBoundsHash, computeContentHash, computeContextHash, computeFieldsContentHash, computeFrameHash, computeIntentDisclosureHash, computeIntentHash, contentCanonicalBytes, decodeAttestationBlob, decodeDidKey, deriveIdentityLine, encodeAttestationBlob, encodeDidKey, frameHash, getAllProfiles, getProfile, intentDisclosureCanonicalBytes, isCommitmentModeAllowed, isFieldBinding, isKeyBearingDid, isV4Attestation, listProfiles, mandateSigningBytes, registerProfile, selectBoundFields, signApproval, signMandateProjection, validateBoundsParams, validateBoundsRequiredFor, validateCommitmentModes, validateContextParams, validateFrameParams, validateSubject, verify, verifyApproval, verifyAttestation, verifyAttestationSignature, verifyAttestationV4, verifyBoundsHash, verifyContextHash, verifyFrameHash, verifyOwnerMandate, verifyOwnerMandates, verifyReceiptSignature };
|
package/dist/index.d.ts
CHANGED
|
@@ -315,6 +315,19 @@ interface ProfileBoundsField {
|
|
|
315
315
|
* kinds, and the same boundType can carry different units.
|
|
316
316
|
*/
|
|
317
317
|
unit?: FieldUnit;
|
|
318
|
+
/**
|
|
319
|
+
* The largest value a mandate may set for this (numeric) bound — a ceiling
|
|
320
|
+
* on what the owner can grant, declared by the profile. E.g. reporting@0.2
|
|
321
|
+
* `read_max_age_days: { maximum: 366 }`: no reporting mandate may read back
|
|
322
|
+
* further than a year.
|
|
323
|
+
*
|
|
324
|
+
* Distinct from the bound itself: the bound limits each ACTION; `maximum`
|
|
325
|
+
* limits the MANDATE. A value above it is not a valid mandate for this
|
|
326
|
+
* profile — the mandate editor caps its input, the issuing Authority Server
|
|
327
|
+
* should refuse it, and an enforcement point that reads the bound applies
|
|
328
|
+
* min(value, maximum). Absent → no ceiling.
|
|
329
|
+
*/
|
|
330
|
+
maximum?: number;
|
|
318
331
|
/** @deprecated v0.4: use boundType instead. */
|
|
319
332
|
constraint?: FieldConstraint;
|
|
320
333
|
/** @deprecated v0.4: use boundType: { kind: 'enum', values: [...] }. */
|
|
@@ -467,6 +480,11 @@ interface ExecutionPath {
|
|
|
467
480
|
*
|
|
468
481
|
* Supports both v0.3 (frameSchema) and v0.4 (boundsSchema + contextSchema).
|
|
469
482
|
*/
|
|
483
|
+
/**
|
|
484
|
+
* A commitment mode a person can choose when signing a mandate. (`review_above_cap`
|
|
485
|
+
* is not chosen by the signer — it follows from team caps.)
|
|
486
|
+
*/
|
|
487
|
+
type SignableCommitmentMode = 'automatic' | 'review';
|
|
470
488
|
interface AgentProfile {
|
|
471
489
|
id: string;
|
|
472
490
|
name?: string;
|
|
@@ -508,6 +526,18 @@ interface AgentProfile {
|
|
|
508
526
|
* a forwarded message has usually lost the footer that carried it.
|
|
509
527
|
*/
|
|
510
528
|
receipt_lookup?: boolean;
|
|
529
|
+
/**
|
|
530
|
+
* The commitment modes a mandate under this profile may be signed with.
|
|
531
|
+
* Absent → every mode (`automatic`, `review`), as before this field existed.
|
|
532
|
+
*
|
|
533
|
+
* Lets a profile be review-only: every action it governs then needs a
|
|
534
|
+
* person's approval, whatever the signer would have picked. The Authority
|
|
535
|
+
* Server refuses to sign a mandate whose `commitment_mode` is not listed;
|
|
536
|
+
* a mandate screen offers only the listed modes. Fail-closed: a declared
|
|
537
|
+
* list with no valid entry allows nothing — a malformed declaration never
|
|
538
|
+
* widens what a profile allows. See {@link allowedCommitmentModes}.
|
|
539
|
+
*/
|
|
540
|
+
commitment_modes?: readonly SignableCommitmentMode[];
|
|
511
541
|
/**
|
|
512
542
|
* v0.3 frame schema (deprecated, kept for backward compat).
|
|
513
543
|
* Used when boundsSchema is not present.
|
|
@@ -1081,6 +1111,31 @@ declare function computeBoundsHash(params: AgentBoundsParams, profile: AgentProf
|
|
|
1081
1111
|
*/
|
|
1082
1112
|
declare function computeContextHash(params: AgentContextParams, profile: AgentProfile): string;
|
|
1083
1113
|
|
|
1114
|
+
/**
|
|
1115
|
+
* Which commitment modes a profile allows its mandates to be signed with
|
|
1116
|
+
* (`AgentProfile.commitment_modes`). One source for the Authority Server's
|
|
1117
|
+
* refusal and the mandate screen's choice, so the two cannot disagree.
|
|
1118
|
+
*/
|
|
1119
|
+
|
|
1120
|
+
/** Every mode a signer can choose, in the order a mandate screen shows them. */
|
|
1121
|
+
declare const SIGNABLE_COMMITMENT_MODES: readonly SignableCommitmentMode[];
|
|
1122
|
+
/**
|
|
1123
|
+
* The modes a mandate under this profile may carry, in display order.
|
|
1124
|
+
* No declaration → all of them. A declaration is read fail-closed: entries
|
|
1125
|
+
* that are not a signable mode are dropped, so a malformed list can only
|
|
1126
|
+
* narrow — `[]`, `"review"` (not a list) or `["reveiw"]` allow nothing.
|
|
1127
|
+
*/
|
|
1128
|
+
declare function allowedCommitmentModes(profile: AgentProfile): readonly SignableCommitmentMode[];
|
|
1129
|
+
/** Whether a mandate under this profile may be signed with `mode`. */
|
|
1130
|
+
declare function isCommitmentModeAllowed(profile: AgentProfile, mode: string): boolean;
|
|
1131
|
+
/**
|
|
1132
|
+
* Authoring check for a profile's `commitment_modes` declaration — for
|
|
1133
|
+
* hap-profiles CI, an authoring tool or a test. Like `validateBoundsRequiredFor`
|
|
1134
|
+
* it is not wired into profile loading; enforcement reads the declaration
|
|
1135
|
+
* fail-closed through `allowedCommitmentModes`. Empty array = nothing to fix.
|
|
1136
|
+
*/
|
|
1137
|
+
declare function validateCommitmentModes(profile: AgentProfile): string[];
|
|
1138
|
+
|
|
1084
1139
|
/**
|
|
1085
1140
|
* Attestation Encoding, Decoding, and Verification
|
|
1086
1141
|
*
|
|
@@ -1401,4 +1456,4 @@ interface ReceiptPayload {
|
|
|
1401
1456
|
*/
|
|
1402
1457
|
declare function verifyReceiptSignature(receipt: ReceiptPayload, publicKeyHex: string): Promise<void>;
|
|
1403
1458
|
|
|
1404
|
-
export { type AgentBoundsParams, type AgentContextParams, type AgentFrameParams, type AgentProfile, type ApprovalObject, type Attestation, type AttestationHeader, type AttestationPayload, type BoundType, CanonicalValueError, type ContentBinding, ContentBindingError, type ContentBindingErrorCode, type CumulativeFieldDef, type CumulativeWindow, type DeclaredFieldDef, type ExecutionContextFieldDef, type ExecutionLogEntry, type ExecutionLogQuery, type ExecutionMappingTransform, type ExecutionMappingValue, type ExecutionPath, type FieldConstraint, type FieldUnit, type GateQuestion, type GatekeeperError, type GatekeeperRequest, type GatekeeperResult, type MandateBinding, MandateError, type MandateProjection, type OwnerMandate, type ProfileBoundsField, type ProfileContextField, type ProfileFrameField, type ProfileToolGating, type ProfileToolGatingEntry, type ReceiptPayload, type ResolvedDomain, type SigningSurface, type Subject, type SubjectValidation, approvalSigningBytes, attestationId, bindingAppliesTo, boundActionTypes, buildMandateProjection, canonicalBounds, canonicalContext, canonicalFrame, canonicalize, canonicalizeText, checkAttestationExpiry, clearProfiles, computeBoundsHash, computeContentHash, computeContextHash, computeFieldsContentHash, computeFrameHash, computeIntentDisclosureHash, computeIntentHash, contentCanonicalBytes, decodeAttestationBlob, decodeDidKey, deriveIdentityLine, encodeAttestationBlob, encodeDidKey, frameHash, getAllProfiles, getProfile, intentDisclosureCanonicalBytes, isFieldBinding, isKeyBearingDid, isV4Attestation, listProfiles, mandateSigningBytes, registerProfile, selectBoundFields, signApproval, signMandateProjection, validateBoundsParams, validateBoundsRequiredFor, validateContextParams, validateFrameParams, validateSubject, verify, verifyApproval, verifyAttestation, verifyAttestationSignature, verifyAttestationV4, verifyBoundsHash, verifyContextHash, verifyFrameHash, verifyOwnerMandate, verifyOwnerMandates, verifyReceiptSignature };
|
|
1459
|
+
export { type AgentBoundsParams, type AgentContextParams, type AgentFrameParams, type AgentProfile, type ApprovalObject, type Attestation, type AttestationHeader, type AttestationPayload, type BoundType, CanonicalValueError, type ContentBinding, ContentBindingError, type ContentBindingErrorCode, type CumulativeFieldDef, type CumulativeWindow, type DeclaredFieldDef, type ExecutionContextFieldDef, type ExecutionLogEntry, type ExecutionLogQuery, type ExecutionMappingTransform, type ExecutionMappingValue, type ExecutionPath, type FieldConstraint, type FieldUnit, type GateQuestion, type GatekeeperError, type GatekeeperRequest, type GatekeeperResult, type MandateBinding, MandateError, type MandateProjection, type OwnerMandate, type ProfileBoundsField, type ProfileContextField, type ProfileFrameField, type ProfileToolGating, type ProfileToolGatingEntry, type ReceiptPayload, type ResolvedDomain, SIGNABLE_COMMITMENT_MODES, type SignableCommitmentMode, type SigningSurface, type Subject, type SubjectValidation, allowedCommitmentModes, approvalSigningBytes, attestationId, bindingAppliesTo, boundActionTypes, buildMandateProjection, canonicalBounds, canonicalContext, canonicalFrame, canonicalize, canonicalizeText, checkAttestationExpiry, clearProfiles, computeBoundsHash, computeContentHash, computeContextHash, computeFieldsContentHash, computeFrameHash, computeIntentDisclosureHash, computeIntentHash, contentCanonicalBytes, decodeAttestationBlob, decodeDidKey, deriveIdentityLine, encodeAttestationBlob, encodeDidKey, frameHash, getAllProfiles, getProfile, intentDisclosureCanonicalBytes, isCommitmentModeAllowed, isFieldBinding, isKeyBearingDid, isV4Attestation, listProfiles, mandateSigningBytes, registerProfile, selectBoundFields, signApproval, signMandateProjection, validateBoundsParams, validateBoundsRequiredFor, validateCommitmentModes, validateContextParams, validateFrameParams, validateSubject, verify, verifyApproval, verifyAttestation, verifyAttestationSignature, verifyAttestationV4, verifyBoundsHash, verifyContextHash, verifyFrameHash, verifyOwnerMandate, verifyOwnerMandates, verifyReceiptSignature };
|
package/dist/index.js
CHANGED
|
@@ -33,6 +33,8 @@ __export(index_exports, {
|
|
|
33
33
|
CanonicalValueError: () => CanonicalValueError,
|
|
34
34
|
ContentBindingError: () => ContentBindingError,
|
|
35
35
|
MandateError: () => MandateError,
|
|
36
|
+
SIGNABLE_COMMITMENT_MODES: () => SIGNABLE_COMMITMENT_MODES,
|
|
37
|
+
allowedCommitmentModes: () => allowedCommitmentModes,
|
|
36
38
|
approvalSigningBytes: () => approvalSigningBytes,
|
|
37
39
|
attestationId: () => attestationId,
|
|
38
40
|
bindingAppliesTo: () => bindingAppliesTo,
|
|
@@ -62,6 +64,7 @@ __export(index_exports, {
|
|
|
62
64
|
getAllProfiles: () => getAllProfiles,
|
|
63
65
|
getProfile: () => getProfile,
|
|
64
66
|
intentDisclosureCanonicalBytes: () => intentDisclosureCanonicalBytes,
|
|
67
|
+
isCommitmentModeAllowed: () => isCommitmentModeAllowed,
|
|
65
68
|
isFieldBinding: () => isFieldBinding,
|
|
66
69
|
isKeyBearingDid: () => isKeyBearingDid,
|
|
67
70
|
isV4Attestation: () => isV4Attestation,
|
|
@@ -73,6 +76,7 @@ __export(index_exports, {
|
|
|
73
76
|
signMandateProjection: () => signMandateProjection,
|
|
74
77
|
validateBoundsParams: () => validateBoundsParams,
|
|
75
78
|
validateBoundsRequiredFor: () => validateBoundsRequiredFor,
|
|
79
|
+
validateCommitmentModes: () => validateCommitmentModes,
|
|
76
80
|
validateContextParams: () => validateContextParams,
|
|
77
81
|
validateFrameParams: () => validateFrameParams,
|
|
78
82
|
validateSubject: () => validateSubject,
|
|
@@ -478,6 +482,33 @@ function computeContextHash(params, profile) {
|
|
|
478
482
|
return `sha256:${hash}`;
|
|
479
483
|
}
|
|
480
484
|
|
|
485
|
+
// src/commitment-modes.ts
|
|
486
|
+
var SIGNABLE_COMMITMENT_MODES = ["review", "automatic"];
|
|
487
|
+
var isSignable = (v) => typeof v === "string" && SIGNABLE_COMMITMENT_MODES.includes(v);
|
|
488
|
+
function allowedCommitmentModes(profile) {
|
|
489
|
+
const declared = profile.commitment_modes;
|
|
490
|
+
if (declared === void 0) return SIGNABLE_COMMITMENT_MODES;
|
|
491
|
+
if (!Array.isArray(declared)) return [];
|
|
492
|
+
return SIGNABLE_COMMITMENT_MODES.filter((m) => declared.includes(m));
|
|
493
|
+
}
|
|
494
|
+
function isCommitmentModeAllowed(profile, mode) {
|
|
495
|
+
return isSignable(mode) && allowedCommitmentModes(profile).includes(mode);
|
|
496
|
+
}
|
|
497
|
+
function validateCommitmentModes(profile) {
|
|
498
|
+
const declared = profile.commitment_modes;
|
|
499
|
+
if (declared === void 0) return [];
|
|
500
|
+
if (!Array.isArray(declared)) return ["commitment_modes must be a list of modes."];
|
|
501
|
+
const errors = [];
|
|
502
|
+
if (declared.length === 0) errors.push("commitment_modes is empty \u2014 no mandate could ever be signed under this profile.");
|
|
503
|
+
const seen = /* @__PURE__ */ new Set();
|
|
504
|
+
for (const m of declared) {
|
|
505
|
+
if (!isSignable(m)) errors.push(`commitment_modes: "${String(m)}" is not a mode a signer can choose (${SIGNABLE_COMMITMENT_MODES.join(", ")}).`);
|
|
506
|
+
if (seen.has(m)) errors.push(`commitment_modes: "${String(m)}" appears twice.`);
|
|
507
|
+
seen.add(m);
|
|
508
|
+
}
|
|
509
|
+
return errors;
|
|
510
|
+
}
|
|
511
|
+
|
|
481
512
|
// src/attestation.ts
|
|
482
513
|
var import_crypto4 = require("crypto");
|
|
483
514
|
var ed = __toESM(require("@noble/ed25519"));
|
|
@@ -1276,6 +1307,8 @@ async function verifyReceiptSignature(receipt, publicKeyHex) {
|
|
|
1276
1307
|
CanonicalValueError,
|
|
1277
1308
|
ContentBindingError,
|
|
1278
1309
|
MandateError,
|
|
1310
|
+
SIGNABLE_COMMITMENT_MODES,
|
|
1311
|
+
allowedCommitmentModes,
|
|
1279
1312
|
approvalSigningBytes,
|
|
1280
1313
|
attestationId,
|
|
1281
1314
|
bindingAppliesTo,
|
|
@@ -1305,6 +1338,7 @@ async function verifyReceiptSignature(receipt, publicKeyHex) {
|
|
|
1305
1338
|
getAllProfiles,
|
|
1306
1339
|
getProfile,
|
|
1307
1340
|
intentDisclosureCanonicalBytes,
|
|
1341
|
+
isCommitmentModeAllowed,
|
|
1308
1342
|
isFieldBinding,
|
|
1309
1343
|
isKeyBearingDid,
|
|
1310
1344
|
isV4Attestation,
|
|
@@ -1316,6 +1350,7 @@ async function verifyReceiptSignature(receipt, publicKeyHex) {
|
|
|
1316
1350
|
signMandateProjection,
|
|
1317
1351
|
validateBoundsParams,
|
|
1318
1352
|
validateBoundsRequiredFor,
|
|
1353
|
+
validateCommitmentModes,
|
|
1319
1354
|
validateContextParams,
|
|
1320
1355
|
validateFrameParams,
|
|
1321
1356
|
validateSubject,
|
package/dist/index.mjs
CHANGED
|
@@ -386,6 +386,33 @@ function computeContextHash(params, profile) {
|
|
|
386
386
|
return `sha256:${hash}`;
|
|
387
387
|
}
|
|
388
388
|
|
|
389
|
+
// src/commitment-modes.ts
|
|
390
|
+
var SIGNABLE_COMMITMENT_MODES = ["review", "automatic"];
|
|
391
|
+
var isSignable = (v) => typeof v === "string" && SIGNABLE_COMMITMENT_MODES.includes(v);
|
|
392
|
+
function allowedCommitmentModes(profile) {
|
|
393
|
+
const declared = profile.commitment_modes;
|
|
394
|
+
if (declared === void 0) return SIGNABLE_COMMITMENT_MODES;
|
|
395
|
+
if (!Array.isArray(declared)) return [];
|
|
396
|
+
return SIGNABLE_COMMITMENT_MODES.filter((m) => declared.includes(m));
|
|
397
|
+
}
|
|
398
|
+
function isCommitmentModeAllowed(profile, mode) {
|
|
399
|
+
return isSignable(mode) && allowedCommitmentModes(profile).includes(mode);
|
|
400
|
+
}
|
|
401
|
+
function validateCommitmentModes(profile) {
|
|
402
|
+
const declared = profile.commitment_modes;
|
|
403
|
+
if (declared === void 0) return [];
|
|
404
|
+
if (!Array.isArray(declared)) return ["commitment_modes must be a list of modes."];
|
|
405
|
+
const errors = [];
|
|
406
|
+
if (declared.length === 0) errors.push("commitment_modes is empty \u2014 no mandate could ever be signed under this profile.");
|
|
407
|
+
const seen = /* @__PURE__ */ new Set();
|
|
408
|
+
for (const m of declared) {
|
|
409
|
+
if (!isSignable(m)) errors.push(`commitment_modes: "${String(m)}" is not a mode a signer can choose (${SIGNABLE_COMMITMENT_MODES.join(", ")}).`);
|
|
410
|
+
if (seen.has(m)) errors.push(`commitment_modes: "${String(m)}" appears twice.`);
|
|
411
|
+
seen.add(m);
|
|
412
|
+
}
|
|
413
|
+
return errors;
|
|
414
|
+
}
|
|
415
|
+
|
|
389
416
|
// src/attestation.ts
|
|
390
417
|
import { createHash as createHash4 } from "crypto";
|
|
391
418
|
import * as ed from "@noble/ed25519";
|
|
@@ -1183,6 +1210,8 @@ export {
|
|
|
1183
1210
|
CanonicalValueError,
|
|
1184
1211
|
ContentBindingError,
|
|
1185
1212
|
MandateError,
|
|
1213
|
+
SIGNABLE_COMMITMENT_MODES,
|
|
1214
|
+
allowedCommitmentModes,
|
|
1186
1215
|
approvalSigningBytes,
|
|
1187
1216
|
attestationId,
|
|
1188
1217
|
bindingAppliesTo,
|
|
@@ -1212,6 +1241,7 @@ export {
|
|
|
1212
1241
|
getAllProfiles,
|
|
1213
1242
|
getProfile,
|
|
1214
1243
|
intentDisclosureCanonicalBytes,
|
|
1244
|
+
isCommitmentModeAllowed,
|
|
1215
1245
|
isFieldBinding,
|
|
1216
1246
|
isKeyBearingDid,
|
|
1217
1247
|
isV4Attestation,
|
|
@@ -1223,6 +1253,7 @@ export {
|
|
|
1223
1253
|
signMandateProjection,
|
|
1224
1254
|
validateBoundsParams,
|
|
1225
1255
|
validateBoundsRequiredFor,
|
|
1256
|
+
validateCommitmentModes,
|
|
1226
1257
|
validateContextParams,
|
|
1227
1258
|
validateFrameParams,
|
|
1228
1259
|
validateSubject,
|
package/package.json
CHANGED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which commitment modes a profile allows its mandates to be signed with
|
|
3
|
+
* (`AgentProfile.commitment_modes`). One source for the Authority Server's
|
|
4
|
+
* refusal and the mandate screen's choice, so the two cannot disagree.
|
|
5
|
+
*/
|
|
6
|
+
import type { AgentProfile, SignableCommitmentMode } from './types';
|
|
7
|
+
|
|
8
|
+
/** Every mode a signer can choose, in the order a mandate screen shows them. */
|
|
9
|
+
export const SIGNABLE_COMMITMENT_MODES: readonly SignableCommitmentMode[] = ['review', 'automatic'];
|
|
10
|
+
|
|
11
|
+
const isSignable = (v: unknown): v is SignableCommitmentMode =>
|
|
12
|
+
typeof v === 'string' && (SIGNABLE_COMMITMENT_MODES as readonly string[]).includes(v);
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* The modes a mandate under this profile may carry, in display order.
|
|
16
|
+
* No declaration → all of them. A declaration is read fail-closed: entries
|
|
17
|
+
* that are not a signable mode are dropped, so a malformed list can only
|
|
18
|
+
* narrow — `[]`, `"review"` (not a list) or `["reveiw"]` allow nothing.
|
|
19
|
+
*/
|
|
20
|
+
export function allowedCommitmentModes(profile: AgentProfile): readonly SignableCommitmentMode[] {
|
|
21
|
+
const declared = (profile as { commitment_modes?: unknown }).commitment_modes;
|
|
22
|
+
if (declared === undefined) return SIGNABLE_COMMITMENT_MODES;
|
|
23
|
+
if (!Array.isArray(declared)) return [];
|
|
24
|
+
return SIGNABLE_COMMITMENT_MODES.filter((m) => declared.includes(m));
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** Whether a mandate under this profile may be signed with `mode`. */
|
|
28
|
+
export function isCommitmentModeAllowed(profile: AgentProfile, mode: string): boolean {
|
|
29
|
+
return isSignable(mode) && allowedCommitmentModes(profile).includes(mode);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Authoring check for a profile's `commitment_modes` declaration — for
|
|
34
|
+
* hap-profiles CI, an authoring tool or a test. Like `validateBoundsRequiredFor`
|
|
35
|
+
* it is not wired into profile loading; enforcement reads the declaration
|
|
36
|
+
* fail-closed through `allowedCommitmentModes`. Empty array = nothing to fix.
|
|
37
|
+
*/
|
|
38
|
+
export function validateCommitmentModes(profile: AgentProfile): string[] {
|
|
39
|
+
const declared = (profile as { commitment_modes?: unknown }).commitment_modes;
|
|
40
|
+
if (declared === undefined) return [];
|
|
41
|
+
if (!Array.isArray(declared)) return ['commitment_modes must be a list of modes.'];
|
|
42
|
+
const errors: string[] = [];
|
|
43
|
+
if (declared.length === 0) errors.push('commitment_modes is empty — no mandate could ever be signed under this profile.');
|
|
44
|
+
const seen = new Set<unknown>();
|
|
45
|
+
for (const m of declared) {
|
|
46
|
+
if (!isSignable(m)) errors.push(`commitment_modes: "${String(m)}" is not a mode a signer can choose (${SIGNABLE_COMMITMENT_MODES.join(', ')}).`);
|
|
47
|
+
if (seen.has(m)) errors.push(`commitment_modes: "${String(m)}" appears twice.`);
|
|
48
|
+
seen.add(m);
|
|
49
|
+
}
|
|
50
|
+
return errors;
|
|
51
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -10,6 +10,7 @@ export * from './content-binding';
|
|
|
10
10
|
export * from './intent-disclosure';
|
|
11
11
|
export * from './identity';
|
|
12
12
|
export * from './frame';
|
|
13
|
+
export * from './commitment-modes';
|
|
13
14
|
export * from './attestation';
|
|
14
15
|
export * from './gatekeeper';
|
|
15
16
|
export * from './profiles';
|
package/src/types.ts
CHANGED
|
@@ -320,6 +320,19 @@ export interface ProfileBoundsField {
|
|
|
320
320
|
* kinds, and the same boundType can carry different units.
|
|
321
321
|
*/
|
|
322
322
|
unit?: FieldUnit;
|
|
323
|
+
/**
|
|
324
|
+
* The largest value a mandate may set for this (numeric) bound — a ceiling
|
|
325
|
+
* on what the owner can grant, declared by the profile. E.g. reporting@0.2
|
|
326
|
+
* `read_max_age_days: { maximum: 366 }`: no reporting mandate may read back
|
|
327
|
+
* further than a year.
|
|
328
|
+
*
|
|
329
|
+
* Distinct from the bound itself: the bound limits each ACTION; `maximum`
|
|
330
|
+
* limits the MANDATE. A value above it is not a valid mandate for this
|
|
331
|
+
* profile — the mandate editor caps its input, the issuing Authority Server
|
|
332
|
+
* should refuse it, and an enforcement point that reads the bound applies
|
|
333
|
+
* min(value, maximum). Absent → no ceiling.
|
|
334
|
+
*/
|
|
335
|
+
maximum?: number;
|
|
323
336
|
/** @deprecated v0.4: use boundType instead. */
|
|
324
337
|
constraint?: FieldConstraint;
|
|
325
338
|
/** @deprecated v0.4: use boundType: { kind: 'enum', values: [...] }. */
|
|
@@ -479,6 +492,12 @@ export interface ExecutionPath {
|
|
|
479
492
|
*
|
|
480
493
|
* Supports both v0.3 (frameSchema) and v0.4 (boundsSchema + contextSchema).
|
|
481
494
|
*/
|
|
495
|
+
/**
|
|
496
|
+
* A commitment mode a person can choose when signing a mandate. (`review_above_cap`
|
|
497
|
+
* is not chosen by the signer — it follows from team caps.)
|
|
498
|
+
*/
|
|
499
|
+
export type SignableCommitmentMode = 'automatic' | 'review';
|
|
500
|
+
|
|
482
501
|
export interface AgentProfile {
|
|
483
502
|
id: string;
|
|
484
503
|
name?: string;
|
|
@@ -523,6 +542,19 @@ export interface AgentProfile {
|
|
|
523
542
|
*/
|
|
524
543
|
receipt_lookup?: boolean;
|
|
525
544
|
|
|
545
|
+
/**
|
|
546
|
+
* The commitment modes a mandate under this profile may be signed with.
|
|
547
|
+
* Absent → every mode (`automatic`, `review`), as before this field existed.
|
|
548
|
+
*
|
|
549
|
+
* Lets a profile be review-only: every action it governs then needs a
|
|
550
|
+
* person's approval, whatever the signer would have picked. The Authority
|
|
551
|
+
* Server refuses to sign a mandate whose `commitment_mode` is not listed;
|
|
552
|
+
* a mandate screen offers only the listed modes. Fail-closed: a declared
|
|
553
|
+
* list with no valid entry allows nothing — a malformed declaration never
|
|
554
|
+
* widens what a profile allows. See {@link allowedCommitmentModes}.
|
|
555
|
+
*/
|
|
556
|
+
commitment_modes?: readonly SignableCommitmentMode[];
|
|
557
|
+
|
|
526
558
|
/**
|
|
527
559
|
* v0.3 frame schema (deprecated, kept for backward compat).
|
|
528
560
|
* Used when boundsSchema is not present.
|