@suveren/gateway 0.13.0 → 0.14.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.
- package/README.md +19 -3
- package/bin/suveren-gateway.js +5 -0
- package/dist/control-plane/index.mjs +146 -114
- package/dist/mcp-server/http.mjs +162 -118
- package/dist/ui/assets/{index-CmLqzgqA.js → index-Cg6VaGKb.js} +12 -12
- package/dist/ui/index.html +1 -1
- package/lib/autostart-templates.mjs +15 -7
- package/node_modules/@hap/core/dist/index.d.mts +49 -1
- package/node_modules/@hap/core/dist/index.d.ts +49 -1
- package/node_modules/@hap/core/dist/index.js +50 -0
- package/node_modules/@hap/core/dist/index.mjs +49 -0
- package/node_modules/@hap/core/package.json +1 -1
- package/node_modules/@hap/core/src/frame.ts +63 -1
- package/node_modules/@hap/core/src/gatekeeper.ts +37 -0
- package/node_modules/@hap/core/src/types.ts +29 -1
- package/node_modules/hono/dist/cjs/hono-base.js +2 -0
- package/node_modules/hono/dist/cjs/middleware/language/language.js +1 -1
- package/node_modules/hono/dist/cjs/middleware/mount/index.js +71 -0
- package/node_modules/hono/dist/cjs/request.js +4 -4
- package/node_modules/hono/dist/hono-base.js +2 -0
- package/node_modules/hono/dist/middleware/mount/index.js +70 -0
- package/node_modules/hono/dist/request.js +4 -4
- package/node_modules/hono/dist/types/hono-base.d.ts +2 -0
- package/node_modules/hono/dist/types/jsx/base.d.ts +1 -1
- package/node_modules/hono/dist/types/middleware/mount/index.d.ts +46 -0
- package/node_modules/hono/dist/types/request.d.ts +4 -4
- package/node_modules/hono/package.json +9 -1
- package/package.json +2 -2
- package/profiles/index.json +3 -1
- package/profiles/purchase/0.6.profile.json +234 -0
- package/profiles/sales/0.3.profile.json +290 -0
- package/server.js +6 -3
package/dist/ui/index.html
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
<meta name="apple-mobile-web-app-title" content="Suveren" />
|
|
15
15
|
<meta name="theme-color" content="#111111" />
|
|
16
16
|
<title>Suveren</title>
|
|
17
|
-
<script type="module" crossorigin src="/assets/index-
|
|
17
|
+
<script type="module" crossorigin src="/assets/index-Cg6VaGKb.js"></script>
|
|
18
18
|
<link rel="stylesheet" crossorigin href="/assets/index-y1OFeYnS.css">
|
|
19
19
|
</head>
|
|
20
20
|
<body>
|
|
@@ -146,8 +146,14 @@ WantedBy=default.target
|
|
|
146
146
|
* carry paths containing spaces.
|
|
147
147
|
*
|
|
148
148
|
* LogonType=InteractiveToken keeps it in the user's own session with no stored
|
|
149
|
-
* password and no admin rights.
|
|
150
|
-
*
|
|
149
|
+
* password and no admin rights. No execution time limit stops it being killed
|
|
150
|
+
* after the default 72 hours. `<Hidden>` only hides the task in the Task
|
|
151
|
+
* Scheduler UI — it does NOT hide the console window: a console program
|
|
152
|
+
* (node.exe, or the installer's launcher.cmd) started by an InteractiveToken
|
|
153
|
+
* task gets a visible console for the gateway's whole lifetime (seen on a real
|
|
154
|
+
* Windows 11 VM; closing it stops the gateway). So the action always runs
|
|
155
|
+
* through `conhost.exe --headless`, Windows' own console host without a
|
|
156
|
+
* window; the real command and its arguments follow it.
|
|
151
157
|
*
|
|
152
158
|
* `userId` is what makes it unprivileged, and leaving it out is not a cosmetic
|
|
153
159
|
* omission: a LogonTrigger with no UserId means "at ANY user's logon", which
|
|
@@ -167,9 +173,8 @@ WantedBy=default.target
|
|
|
167
173
|
* into offline+managed mode too. Routing the scheduled task through the
|
|
168
174
|
* launcher instead keeps that env scoped to just this one process tree: the
|
|
169
175
|
* launcher sets it for its own child (server.js) only. Omitted (the npm/dev
|
|
170
|
-
* CLI's `service install`, which has no launcher),
|
|
171
|
-
*
|
|
172
|
-
* any install that isn't the managed Windows one.
|
|
176
|
+
* CLI's `service install`, which has no launcher), the default node.exe
|
|
177
|
+
* action is used. Either way it is wrapped in conhost.exe --headless.
|
|
173
178
|
*/
|
|
174
179
|
export function buildWindowsTaskXml({ nodePath, serverEntry, author, dataDir, userId, command, args: argsOverride }) {
|
|
175
180
|
// Task Scheduler requires \Command to be the executable and \Arguments the
|
|
@@ -177,8 +182,11 @@ export function buildWindowsTaskXml({ nodePath, serverEntry, author, dataDir, us
|
|
|
177
182
|
// Task Scheduler XML carries no environment block, so the marker that this
|
|
178
183
|
// was a service start has to ride in the arguments (or, for a launcher
|
|
179
184
|
// command, is the launcher's own job to pass through).
|
|
180
|
-
const
|
|
181
|
-
const
|
|
185
|
+
const realCommand = command ?? nodePath;
|
|
186
|
+
const realArgs = argsOverride ?? `"${serverEntry}" --autostart`;
|
|
187
|
+
// No visible console window (see above): conhost.exe --headless "<real command>" <args>.
|
|
188
|
+
const resolvedCommand = '%SystemRoot%\\System32\\conhost.exe';
|
|
189
|
+
const args = `--headless "${realCommand}" ${realArgs}`;
|
|
182
190
|
const envNote = dataDir ? `Suveren data directory: ${dataDir}` : 'Suveren gateway';
|
|
183
191
|
|
|
184
192
|
// Element order is fixed by the Task Scheduler XSD, and schtasks rejects the
|
|
@@ -205,10 +205,29 @@ type BoundType =
|
|
|
205
205
|
* Per-transaction cap. The execution context field named in `of` must
|
|
206
206
|
* satisfy `execution[of] <= bound` for the current call. No cumulative
|
|
207
207
|
* tracking. Used by: amount_max, recipient_max, booking_duration_max, etc.
|
|
208
|
+
*
|
|
209
|
+
* `requiredFor` (v0.8+) closes the converse: without it, a call that does
|
|
210
|
+
* not carry `of` at all is simply skipped — a 5,000 cap refuses 6,000 but
|
|
211
|
+
* permits a call that declares no value whatsoever, which is indistinguishable
|
|
212
|
+
* from an unenforced bound. The same hole, and the same fix, as
|
|
213
|
+
* `FieldConstraint.requiredFor` on a scope constraint (below): values drawn
|
|
214
|
+
* from the profile's `boundsSchema.actionTypes` registry. For a listed
|
|
215
|
+
* `action_type`, an execution whose context lacks `of` — or whose value is
|
|
216
|
+
* not a finite number — MUST be refused rather than skipped. For an
|
|
217
|
+
* unlisted (or when `requiredFor` is absent) action type, today's
|
|
218
|
+
* skip-on-absence behaviour is unchanged. Meaningful only on
|
|
219
|
+
* `per_transaction`; the other `BoundType` kinds have no per-call "value
|
|
220
|
+
* exposed or not" question — `cumulative_sum`/`cumulative_count` always read
|
|
221
|
+
* from the execution log regardless of what this call declares, and `enum`
|
|
222
|
+
* is a capability flag, not a runtime value — so the field does not exist
|
|
223
|
+
* on those variants and a profile that puts it there has it silently
|
|
224
|
+
* ignored by every enforcement point (TypeScript also refuses it when the
|
|
225
|
+
* profile is authored against this type rather than raw JSON).
|
|
208
226
|
*/
|
|
209
227
|
{
|
|
210
228
|
kind: 'per_transaction';
|
|
211
229
|
of: string;
|
|
230
|
+
requiredFor?: string[];
|
|
212
231
|
}
|
|
213
232
|
/**
|
|
214
233
|
* Cumulative sum within a time window. The SP maintains a running sum
|
|
@@ -503,6 +522,16 @@ interface AgentProfile {
|
|
|
503
522
|
boundsSchema?: {
|
|
504
523
|
keyOrder: string[];
|
|
505
524
|
fields: Record<string, ProfileBoundsField>;
|
|
525
|
+
/**
|
|
526
|
+
* v0.5+ registry of the action types this profile recognizes (e.g.
|
|
527
|
+
* `["send", "delete", "setup"]`). Every `execution.action_type` the
|
|
528
|
+
* Authority Server and gateway accept for this profile MUST be a member
|
|
529
|
+
* when the registry is declared (protocol.md → Bounds Schema, rule 2);
|
|
530
|
+
* it is also what a `per_transaction` bound's `requiredFor` draws from.
|
|
531
|
+
* Absent on profiles published before the registry existed — membership
|
|
532
|
+
* is then uncheckable, not a violation.
|
|
533
|
+
*/
|
|
534
|
+
actionTypes?: readonly string[];
|
|
506
535
|
};
|
|
507
536
|
/**
|
|
508
537
|
* v0.4 context schema — defines the execution context parameters (e.g., currency, action_type).
|
|
@@ -983,6 +1012,25 @@ declare function validateContextParams(params: AgentContextParams, profile: Agen
|
|
|
983
1012
|
valid: boolean;
|
|
984
1013
|
errors: string[];
|
|
985
1014
|
};
|
|
1015
|
+
/**
|
|
1016
|
+
* Authoring-time check for `per_transaction` bound `requiredFor` (v0.8+):
|
|
1017
|
+
* entries must name a real `action_type` from the profile's declared
|
|
1018
|
+
* `boundsSchema.actionTypes` registry, and the field is only meaningful on
|
|
1019
|
+
* `per_transaction` bounds (see `BoundType`'s doc comment for why the other
|
|
1020
|
+
* kinds don't carry it).
|
|
1021
|
+
*
|
|
1022
|
+
* This is NOT wired into `registerProfile` or any enforcement path — nothing
|
|
1023
|
+
* in hap-core validates profile JSON at load time today (the pre-existing
|
|
1024
|
+
* `requiredFor` on a context/scope constraint has the same gap), so adding
|
|
1025
|
+
* an automatic refusal here would be new behaviour beyond this change's
|
|
1026
|
+
* scope. Call it explicitly from an authoring tool, a hap-profiles CI check,
|
|
1027
|
+
* or a test, to catch a `requiredFor` entry that can never match (misspelled
|
|
1028
|
+
* action type) or is attached to a bound kind that silently ignores it.
|
|
1029
|
+
*
|
|
1030
|
+
* Returns an empty array when the profile has no boundsSchema or nothing to
|
|
1031
|
+
* check — never throws.
|
|
1032
|
+
*/
|
|
1033
|
+
declare function validateBoundsRequiredFor(profile: AgentProfile): string[];
|
|
986
1034
|
/**
|
|
987
1035
|
* Thrown when a value cannot be canonicalized at all — currently only for raw
|
|
988
1036
|
* LF/CR inside a value. Carries the protocol error code so callers can map it
|
|
@@ -1353,4 +1401,4 @@ interface ReceiptPayload {
|
|
|
1353
1401
|
*/
|
|
1354
1402
|
declare function verifyReceiptSignature(receipt: ReceiptPayload, publicKeyHex: string): Promise<void>;
|
|
1355
1403
|
|
|
1356
|
-
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, validateContextParams, validateFrameParams, validateSubject, verify, verifyApproval, verifyAttestation, verifyAttestationSignature, verifyAttestationV4, verifyBoundsHash, verifyContextHash, verifyFrameHash, verifyOwnerMandate, verifyOwnerMandates, verifyReceiptSignature };
|
|
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 };
|
|
@@ -205,10 +205,29 @@ type BoundType =
|
|
|
205
205
|
* Per-transaction cap. The execution context field named in `of` must
|
|
206
206
|
* satisfy `execution[of] <= bound` for the current call. No cumulative
|
|
207
207
|
* tracking. Used by: amount_max, recipient_max, booking_duration_max, etc.
|
|
208
|
+
*
|
|
209
|
+
* `requiredFor` (v0.8+) closes the converse: without it, a call that does
|
|
210
|
+
* not carry `of` at all is simply skipped — a 5,000 cap refuses 6,000 but
|
|
211
|
+
* permits a call that declares no value whatsoever, which is indistinguishable
|
|
212
|
+
* from an unenforced bound. The same hole, and the same fix, as
|
|
213
|
+
* `FieldConstraint.requiredFor` on a scope constraint (below): values drawn
|
|
214
|
+
* from the profile's `boundsSchema.actionTypes` registry. For a listed
|
|
215
|
+
* `action_type`, an execution whose context lacks `of` — or whose value is
|
|
216
|
+
* not a finite number — MUST be refused rather than skipped. For an
|
|
217
|
+
* unlisted (or when `requiredFor` is absent) action type, today's
|
|
218
|
+
* skip-on-absence behaviour is unchanged. Meaningful only on
|
|
219
|
+
* `per_transaction`; the other `BoundType` kinds have no per-call "value
|
|
220
|
+
* exposed or not" question — `cumulative_sum`/`cumulative_count` always read
|
|
221
|
+
* from the execution log regardless of what this call declares, and `enum`
|
|
222
|
+
* is a capability flag, not a runtime value — so the field does not exist
|
|
223
|
+
* on those variants and a profile that puts it there has it silently
|
|
224
|
+
* ignored by every enforcement point (TypeScript also refuses it when the
|
|
225
|
+
* profile is authored against this type rather than raw JSON).
|
|
208
226
|
*/
|
|
209
227
|
{
|
|
210
228
|
kind: 'per_transaction';
|
|
211
229
|
of: string;
|
|
230
|
+
requiredFor?: string[];
|
|
212
231
|
}
|
|
213
232
|
/**
|
|
214
233
|
* Cumulative sum within a time window. The SP maintains a running sum
|
|
@@ -503,6 +522,16 @@ interface AgentProfile {
|
|
|
503
522
|
boundsSchema?: {
|
|
504
523
|
keyOrder: string[];
|
|
505
524
|
fields: Record<string, ProfileBoundsField>;
|
|
525
|
+
/**
|
|
526
|
+
* v0.5+ registry of the action types this profile recognizes (e.g.
|
|
527
|
+
* `["send", "delete", "setup"]`). Every `execution.action_type` the
|
|
528
|
+
* Authority Server and gateway accept for this profile MUST be a member
|
|
529
|
+
* when the registry is declared (protocol.md → Bounds Schema, rule 2);
|
|
530
|
+
* it is also what a `per_transaction` bound's `requiredFor` draws from.
|
|
531
|
+
* Absent on profiles published before the registry existed — membership
|
|
532
|
+
* is then uncheckable, not a violation.
|
|
533
|
+
*/
|
|
534
|
+
actionTypes?: readonly string[];
|
|
506
535
|
};
|
|
507
536
|
/**
|
|
508
537
|
* v0.4 context schema — defines the execution context parameters (e.g., currency, action_type).
|
|
@@ -983,6 +1012,25 @@ declare function validateContextParams(params: AgentContextParams, profile: Agen
|
|
|
983
1012
|
valid: boolean;
|
|
984
1013
|
errors: string[];
|
|
985
1014
|
};
|
|
1015
|
+
/**
|
|
1016
|
+
* Authoring-time check for `per_transaction` bound `requiredFor` (v0.8+):
|
|
1017
|
+
* entries must name a real `action_type` from the profile's declared
|
|
1018
|
+
* `boundsSchema.actionTypes` registry, and the field is only meaningful on
|
|
1019
|
+
* `per_transaction` bounds (see `BoundType`'s doc comment for why the other
|
|
1020
|
+
* kinds don't carry it).
|
|
1021
|
+
*
|
|
1022
|
+
* This is NOT wired into `registerProfile` or any enforcement path — nothing
|
|
1023
|
+
* in hap-core validates profile JSON at load time today (the pre-existing
|
|
1024
|
+
* `requiredFor` on a context/scope constraint has the same gap), so adding
|
|
1025
|
+
* an automatic refusal here would be new behaviour beyond this change's
|
|
1026
|
+
* scope. Call it explicitly from an authoring tool, a hap-profiles CI check,
|
|
1027
|
+
* or a test, to catch a `requiredFor` entry that can never match (misspelled
|
|
1028
|
+
* action type) or is attached to a bound kind that silently ignores it.
|
|
1029
|
+
*
|
|
1030
|
+
* Returns an empty array when the profile has no boundsSchema or nothing to
|
|
1031
|
+
* check — never throws.
|
|
1032
|
+
*/
|
|
1033
|
+
declare function validateBoundsRequiredFor(profile: AgentProfile): string[];
|
|
986
1034
|
/**
|
|
987
1035
|
* Thrown when a value cannot be canonicalized at all — currently only for raw
|
|
988
1036
|
* LF/CR inside a value. Carries the protocol error code so callers can map it
|
|
@@ -1353,4 +1401,4 @@ interface ReceiptPayload {
|
|
|
1353
1401
|
*/
|
|
1354
1402
|
declare function verifyReceiptSignature(receipt: ReceiptPayload, publicKeyHex: string): Promise<void>;
|
|
1355
1403
|
|
|
1356
|
-
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, validateContextParams, validateFrameParams, validateSubject, verify, verifyApproval, verifyAttestation, verifyAttestationSignature, verifyAttestationV4, verifyBoundsHash, verifyContextHash, verifyFrameHash, verifyOwnerMandate, verifyOwnerMandates, verifyReceiptSignature };
|
|
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 };
|
|
@@ -72,6 +72,7 @@ __export(index_exports, {
|
|
|
72
72
|
signApproval: () => signApproval,
|
|
73
73
|
signMandateProjection: () => signMandateProjection,
|
|
74
74
|
validateBoundsParams: () => validateBoundsParams,
|
|
75
|
+
validateBoundsRequiredFor: () => validateBoundsRequiredFor,
|
|
75
76
|
validateContextParams: () => validateContextParams,
|
|
76
77
|
validateFrameParams: () => validateFrameParams,
|
|
77
78
|
validateSubject: () => validateSubject,
|
|
@@ -378,6 +379,38 @@ function validateContextParams(params, profile) {
|
|
|
378
379
|
}
|
|
379
380
|
return { valid: errors.length === 0, errors };
|
|
380
381
|
}
|
|
382
|
+
function validateBoundsRequiredFor(profile) {
|
|
383
|
+
const errors = [];
|
|
384
|
+
const boundsSchema = profile.boundsSchema;
|
|
385
|
+
if (!boundsSchema) return errors;
|
|
386
|
+
const actionTypes = boundsSchema.actionTypes ? [...boundsSchema.actionTypes] : void 0;
|
|
387
|
+
for (const [fieldName, fieldDef] of Object.entries(boundsSchema.fields)) {
|
|
388
|
+
const bt = fieldDef.boundType;
|
|
389
|
+
if (!bt) continue;
|
|
390
|
+
const requiredFor = bt.requiredFor;
|
|
391
|
+
if (requiredFor === void 0) continue;
|
|
392
|
+
if (!Array.isArray(requiredFor) || !requiredFor.every((v) => typeof v === "string")) {
|
|
393
|
+
errors.push(`Bound "${fieldName}": requiredFor must be a string array.`);
|
|
394
|
+
continue;
|
|
395
|
+
}
|
|
396
|
+
if (bt.kind !== "per_transaction") {
|
|
397
|
+
errors.push(
|
|
398
|
+
`Bound "${fieldName}": requiredFor is only meaningful on a per_transaction bound (found on kind "${bt.kind}") \u2014 every enforcement point ignores it there. Remove it.`
|
|
399
|
+
);
|
|
400
|
+
continue;
|
|
401
|
+
}
|
|
402
|
+
if (actionTypes) {
|
|
403
|
+
for (const actionType of requiredFor) {
|
|
404
|
+
if (!actionTypes.includes(actionType)) {
|
|
405
|
+
errors.push(
|
|
406
|
+
`Bound "${fieldName}": requiredFor names action type "${actionType}", which is not in this profile's boundsSchema.actionTypes registry [${actionTypes.join(", ")}]. It can never match a real execution and the requirement is dead.`
|
|
407
|
+
);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
return errors;
|
|
413
|
+
}
|
|
381
414
|
var CanonicalValueError = class extends Error {
|
|
382
415
|
code;
|
|
383
416
|
field;
|
|
@@ -820,6 +853,22 @@ function checkBoundsV4(request, profile, executionLog, now) {
|
|
|
820
853
|
switch (bt.kind) {
|
|
821
854
|
case "per_transaction": {
|
|
822
855
|
const actual = request.execution[bt.of];
|
|
856
|
+
const engaged = !!bt.requiredFor?.length && actionType !== void 0 && bt.requiredFor.includes(actionType);
|
|
857
|
+
if (engaged) {
|
|
858
|
+
const missing = actual === void 0 || actual === null;
|
|
859
|
+
const numericActual = missing ? NaN : typeof actual === "number" ? actual : Number(actual);
|
|
860
|
+
const missingOrNonNumeric = missing || Number.isNaN(numericActual);
|
|
861
|
+
if (missingOrNonNumeric) {
|
|
862
|
+
errors.push({
|
|
863
|
+
code: "BOUND_EXCEEDED",
|
|
864
|
+
field: bt.of,
|
|
865
|
+
message: missing ? `Bound "${fieldName}" requires "${bt.of}" for "${actionType}" calls, but this call exposes no ${bt.of} to check against it. Refusing: the call cannot be shown to stay within ${fieldName}.` : `Bound "${fieldName}" requires a numeric "${bt.of}" for "${actionType}" calls, but this call's value (${String(actual)}) is not a number. Refusing: the call cannot be shown to stay within ${fieldName}.`,
|
|
866
|
+
bound: boundValue,
|
|
867
|
+
actual
|
|
868
|
+
});
|
|
869
|
+
continue;
|
|
870
|
+
}
|
|
871
|
+
}
|
|
823
872
|
if (actual === void 0) continue;
|
|
824
873
|
if (typeof boundValue !== "number" || typeof actual !== "number") {
|
|
825
874
|
errors.push({
|
|
@@ -1266,6 +1315,7 @@ async function verifyReceiptSignature(receipt, publicKeyHex) {
|
|
|
1266
1315
|
signApproval,
|
|
1267
1316
|
signMandateProjection,
|
|
1268
1317
|
validateBoundsParams,
|
|
1318
|
+
validateBoundsRequiredFor,
|
|
1269
1319
|
validateContextParams,
|
|
1270
1320
|
validateFrameParams,
|
|
1271
1321
|
validateSubject,
|
|
@@ -287,6 +287,38 @@ function validateContextParams(params, profile) {
|
|
|
287
287
|
}
|
|
288
288
|
return { valid: errors.length === 0, errors };
|
|
289
289
|
}
|
|
290
|
+
function validateBoundsRequiredFor(profile) {
|
|
291
|
+
const errors = [];
|
|
292
|
+
const boundsSchema = profile.boundsSchema;
|
|
293
|
+
if (!boundsSchema) return errors;
|
|
294
|
+
const actionTypes = boundsSchema.actionTypes ? [...boundsSchema.actionTypes] : void 0;
|
|
295
|
+
for (const [fieldName, fieldDef] of Object.entries(boundsSchema.fields)) {
|
|
296
|
+
const bt = fieldDef.boundType;
|
|
297
|
+
if (!bt) continue;
|
|
298
|
+
const requiredFor = bt.requiredFor;
|
|
299
|
+
if (requiredFor === void 0) continue;
|
|
300
|
+
if (!Array.isArray(requiredFor) || !requiredFor.every((v) => typeof v === "string")) {
|
|
301
|
+
errors.push(`Bound "${fieldName}": requiredFor must be a string array.`);
|
|
302
|
+
continue;
|
|
303
|
+
}
|
|
304
|
+
if (bt.kind !== "per_transaction") {
|
|
305
|
+
errors.push(
|
|
306
|
+
`Bound "${fieldName}": requiredFor is only meaningful on a per_transaction bound (found on kind "${bt.kind}") \u2014 every enforcement point ignores it there. Remove it.`
|
|
307
|
+
);
|
|
308
|
+
continue;
|
|
309
|
+
}
|
|
310
|
+
if (actionTypes) {
|
|
311
|
+
for (const actionType of requiredFor) {
|
|
312
|
+
if (!actionTypes.includes(actionType)) {
|
|
313
|
+
errors.push(
|
|
314
|
+
`Bound "${fieldName}": requiredFor names action type "${actionType}", which is not in this profile's boundsSchema.actionTypes registry [${actionTypes.join(", ")}]. It can never match a real execution and the requirement is dead.`
|
|
315
|
+
);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
return errors;
|
|
321
|
+
}
|
|
290
322
|
var CanonicalValueError = class extends Error {
|
|
291
323
|
code;
|
|
292
324
|
field;
|
|
@@ -729,6 +761,22 @@ function checkBoundsV4(request, profile, executionLog, now) {
|
|
|
729
761
|
switch (bt.kind) {
|
|
730
762
|
case "per_transaction": {
|
|
731
763
|
const actual = request.execution[bt.of];
|
|
764
|
+
const engaged = !!bt.requiredFor?.length && actionType !== void 0 && bt.requiredFor.includes(actionType);
|
|
765
|
+
if (engaged) {
|
|
766
|
+
const missing = actual === void 0 || actual === null;
|
|
767
|
+
const numericActual = missing ? NaN : typeof actual === "number" ? actual : Number(actual);
|
|
768
|
+
const missingOrNonNumeric = missing || Number.isNaN(numericActual);
|
|
769
|
+
if (missingOrNonNumeric) {
|
|
770
|
+
errors.push({
|
|
771
|
+
code: "BOUND_EXCEEDED",
|
|
772
|
+
field: bt.of,
|
|
773
|
+
message: missing ? `Bound "${fieldName}" requires "${bt.of}" for "${actionType}" calls, but this call exposes no ${bt.of} to check against it. Refusing: the call cannot be shown to stay within ${fieldName}.` : `Bound "${fieldName}" requires a numeric "${bt.of}" for "${actionType}" calls, but this call's value (${String(actual)}) is not a number. Refusing: the call cannot be shown to stay within ${fieldName}.`,
|
|
774
|
+
bound: boundValue,
|
|
775
|
+
actual
|
|
776
|
+
});
|
|
777
|
+
continue;
|
|
778
|
+
}
|
|
779
|
+
}
|
|
732
780
|
if (actual === void 0) continue;
|
|
733
781
|
if (typeof boundValue !== "number" || typeof actual !== "number") {
|
|
734
782
|
errors.push({
|
|
@@ -1174,6 +1222,7 @@ export {
|
|
|
1174
1222
|
signApproval,
|
|
1175
1223
|
signMandateProjection,
|
|
1176
1224
|
validateBoundsParams,
|
|
1225
|
+
validateBoundsRequiredFor,
|
|
1177
1226
|
validateContextParams,
|
|
1178
1227
|
validateFrameParams,
|
|
1179
1228
|
validateSubject,
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
15
|
import { createHash } from 'crypto';
|
|
16
|
-
import type { AgentFrameParams, AgentBoundsParams, AgentContextParams, AgentProfile } from './types';
|
|
16
|
+
import type { AgentFrameParams, AgentBoundsParams, AgentContextParams, AgentProfile, BoundType } from './types';
|
|
17
17
|
|
|
18
18
|
// ─── v0.3 Frame Functions ─────────────────────────────────────────────────────
|
|
19
19
|
|
|
@@ -179,6 +179,68 @@ export function validateContextParams(
|
|
|
179
179
|
return { valid: errors.length === 0, errors };
|
|
180
180
|
}
|
|
181
181
|
|
|
182
|
+
/**
|
|
183
|
+
* Authoring-time check for `per_transaction` bound `requiredFor` (v0.8+):
|
|
184
|
+
* entries must name a real `action_type` from the profile's declared
|
|
185
|
+
* `boundsSchema.actionTypes` registry, and the field is only meaningful on
|
|
186
|
+
* `per_transaction` bounds (see `BoundType`'s doc comment for why the other
|
|
187
|
+
* kinds don't carry it).
|
|
188
|
+
*
|
|
189
|
+
* This is NOT wired into `registerProfile` or any enforcement path — nothing
|
|
190
|
+
* in hap-core validates profile JSON at load time today (the pre-existing
|
|
191
|
+
* `requiredFor` on a context/scope constraint has the same gap), so adding
|
|
192
|
+
* an automatic refusal here would be new behaviour beyond this change's
|
|
193
|
+
* scope. Call it explicitly from an authoring tool, a hap-profiles CI check,
|
|
194
|
+
* or a test, to catch a `requiredFor` entry that can never match (misspelled
|
|
195
|
+
* action type) or is attached to a bound kind that silently ignores it.
|
|
196
|
+
*
|
|
197
|
+
* Returns an empty array when the profile has no boundsSchema or nothing to
|
|
198
|
+
* check — never throws.
|
|
199
|
+
*/
|
|
200
|
+
export function validateBoundsRequiredFor(profile: AgentProfile): string[] {
|
|
201
|
+
const errors: string[] = [];
|
|
202
|
+
const boundsSchema = profile.boundsSchema;
|
|
203
|
+
if (!boundsSchema) return errors;
|
|
204
|
+
|
|
205
|
+
const actionTypes = boundsSchema.actionTypes ? [...boundsSchema.actionTypes] : undefined;
|
|
206
|
+
|
|
207
|
+
for (const [fieldName, fieldDef] of Object.entries(boundsSchema.fields)) {
|
|
208
|
+
const bt = fieldDef.boundType as (BoundType & { requiredFor?: unknown }) | undefined;
|
|
209
|
+
if (!bt) continue;
|
|
210
|
+
const requiredFor = (bt as { requiredFor?: unknown }).requiredFor;
|
|
211
|
+
if (requiredFor === undefined) continue;
|
|
212
|
+
|
|
213
|
+
if (!Array.isArray(requiredFor) || !requiredFor.every((v) => typeof v === 'string')) {
|
|
214
|
+
errors.push(`Bound "${fieldName}": requiredFor must be a string array.`);
|
|
215
|
+
continue;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
if (bt.kind !== 'per_transaction') {
|
|
219
|
+
errors.push(
|
|
220
|
+
`Bound "${fieldName}": requiredFor is only meaningful on a per_transaction bound ` +
|
|
221
|
+
`(found on kind "${bt.kind}") — every enforcement point ignores it there. Remove it.`,
|
|
222
|
+
);
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
if (actionTypes) {
|
|
227
|
+
for (const actionType of requiredFor) {
|
|
228
|
+
if (!actionTypes.includes(actionType)) {
|
|
229
|
+
errors.push(
|
|
230
|
+
`Bound "${fieldName}": requiredFor names action type "${actionType}", which is not ` +
|
|
231
|
+
`in this profile's boundsSchema.actionTypes registry [${actionTypes.join(', ')}]. ` +
|
|
232
|
+
`It can never match a real execution and the requirement is dead.`,
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
// No actionTypes registry declared: membership cannot be checked (same
|
|
238
|
+
// tolerance the AS receipt route applies to pre-registry profiles).
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
return errors;
|
|
242
|
+
}
|
|
243
|
+
|
|
182
244
|
// ─── Value Encoding (normative, v0.5+) ───────────────────────────────────────
|
|
183
245
|
|
|
184
246
|
/**
|
|
@@ -546,6 +546,43 @@ function checkBoundsV4(
|
|
|
546
546
|
switch (bt.kind) {
|
|
547
547
|
case 'per_transaction': {
|
|
548
548
|
const actual = request.execution[bt.of];
|
|
549
|
+
|
|
550
|
+
// `requiredFor`: for a listed action_type, absence (or a non-numeric
|
|
551
|
+
// value) is a denial, not a skip — see BoundType.per_transaction's
|
|
552
|
+
// doc comment for why. Unlisted action types, or no `requiredFor` at
|
|
553
|
+
// all, keep the pre-existing skip-on-absence behaviour below.
|
|
554
|
+
const engaged = !!bt.requiredFor?.length
|
|
555
|
+
&& actionType !== undefined
|
|
556
|
+
&& bt.requiredFor.includes(actionType);
|
|
557
|
+
|
|
558
|
+
if (engaged) {
|
|
559
|
+
// `null` is treated as "missing", not as the number 0 — JSON has no
|
|
560
|
+
// undefined, so a value lost somewhere upstream (an unmapped
|
|
561
|
+
// connector field serialized through JSON) commonly arrives as
|
|
562
|
+
// null. `Number(null) === 0` would otherwise read as "an amount of
|
|
563
|
+
// zero was declared and is within bound", which is the exact
|
|
564
|
+
// silent-pass this feature exists to close.
|
|
565
|
+
const missing = actual === undefined || actual === null;
|
|
566
|
+
const numericActual = missing ? NaN : (typeof actual === 'number' ? actual : Number(actual));
|
|
567
|
+
const missingOrNonNumeric = missing || Number.isNaN(numericActual);
|
|
568
|
+
if (missingOrNonNumeric) {
|
|
569
|
+
errors.push({
|
|
570
|
+
code: 'BOUND_EXCEEDED',
|
|
571
|
+
field: bt.of,
|
|
572
|
+
message: missing
|
|
573
|
+
? `Bound "${fieldName}" requires "${bt.of}" for "${actionType}" calls, but this ` +
|
|
574
|
+
`call exposes no ${bt.of} to check against it. Refusing: the call cannot be ` +
|
|
575
|
+
`shown to stay within ${fieldName}.`
|
|
576
|
+
: `Bound "${fieldName}" requires a numeric "${bt.of}" for "${actionType}" calls, ` +
|
|
577
|
+
`but this call's value (${String(actual)}) is not a number. Refusing: the call ` +
|
|
578
|
+
`cannot be shown to stay within ${fieldName}.`,
|
|
579
|
+
bound: boundValue,
|
|
580
|
+
actual,
|
|
581
|
+
});
|
|
582
|
+
continue;
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
|
|
549
586
|
if (actual === undefined) continue;
|
|
550
587
|
if (typeof boundValue !== 'number' || typeof actual !== 'number') {
|
|
551
588
|
errors.push({
|
|
@@ -218,8 +218,26 @@ export type BoundType =
|
|
|
218
218
|
* Per-transaction cap. The execution context field named in `of` must
|
|
219
219
|
* satisfy `execution[of] <= bound` for the current call. No cumulative
|
|
220
220
|
* tracking. Used by: amount_max, recipient_max, booking_duration_max, etc.
|
|
221
|
+
*
|
|
222
|
+
* `requiredFor` (v0.8+) closes the converse: without it, a call that does
|
|
223
|
+
* not carry `of` at all is simply skipped — a 5,000 cap refuses 6,000 but
|
|
224
|
+
* permits a call that declares no value whatsoever, which is indistinguishable
|
|
225
|
+
* from an unenforced bound. The same hole, and the same fix, as
|
|
226
|
+
* `FieldConstraint.requiredFor` on a scope constraint (below): values drawn
|
|
227
|
+
* from the profile's `boundsSchema.actionTypes` registry. For a listed
|
|
228
|
+
* `action_type`, an execution whose context lacks `of` — or whose value is
|
|
229
|
+
* not a finite number — MUST be refused rather than skipped. For an
|
|
230
|
+
* unlisted (or when `requiredFor` is absent) action type, today's
|
|
231
|
+
* skip-on-absence behaviour is unchanged. Meaningful only on
|
|
232
|
+
* `per_transaction`; the other `BoundType` kinds have no per-call "value
|
|
233
|
+
* exposed or not" question — `cumulative_sum`/`cumulative_count` always read
|
|
234
|
+
* from the execution log regardless of what this call declares, and `enum`
|
|
235
|
+
* is a capability flag, not a runtime value — so the field does not exist
|
|
236
|
+
* on those variants and a profile that puts it there has it silently
|
|
237
|
+
* ignored by every enforcement point (TypeScript also refuses it when the
|
|
238
|
+
* profile is authored against this type rather than raw JSON).
|
|
221
239
|
*/
|
|
222
|
-
| { kind: 'per_transaction'; of: string }
|
|
240
|
+
| { kind: 'per_transaction'; of: string; requiredFor?: string[] }
|
|
223
241
|
/**
|
|
224
242
|
* Cumulative sum within a time window. The SP maintains a running sum
|
|
225
243
|
* of `execution[of]` across all prior executions in the window; the
|
|
@@ -520,6 +538,16 @@ export interface AgentProfile {
|
|
|
520
538
|
boundsSchema?: {
|
|
521
539
|
keyOrder: string[];
|
|
522
540
|
fields: Record<string, ProfileBoundsField>;
|
|
541
|
+
/**
|
|
542
|
+
* v0.5+ registry of the action types this profile recognizes (e.g.
|
|
543
|
+
* `["send", "delete", "setup"]`). Every `execution.action_type` the
|
|
544
|
+
* Authority Server and gateway accept for this profile MUST be a member
|
|
545
|
+
* when the registry is declared (protocol.md → Bounds Schema, rule 2);
|
|
546
|
+
* it is also what a `per_transaction` bound's `requiredFor` draws from.
|
|
547
|
+
* Absent on profiles published before the registry existed — membership
|
|
548
|
+
* is then uncheckable, not a violation.
|
|
549
|
+
*/
|
|
550
|
+
actionTypes?: readonly string[];
|
|
523
551
|
};
|
|
524
552
|
|
|
525
553
|
/**
|
|
@@ -176,6 +176,8 @@ var Hono = class Hono {
|
|
|
176
176
|
/**
|
|
177
177
|
* `.mount()` allows you to mount applications built with other frameworks into your Hono application.
|
|
178
178
|
*
|
|
179
|
+
* @deprecated Use `mount()` from `hono/mount` instead. `.mount()` will be removed in v5.
|
|
180
|
+
*
|
|
179
181
|
* @see {@link https://hono.dev/docs/api/hono#mount}
|
|
180
182
|
*
|
|
181
183
|
* @param {string} path - base Path
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_helper_cookie_index = require("../../helper/cookie/index.js");
|
|
3
2
|
const require_utils_accept = require("../../utils/accept.js");
|
|
3
|
+
const require_helper_cookie_index = require("../../helper/cookie/index.js");
|
|
4
4
|
//#region src/middleware/language/language.ts
|
|
5
5
|
const DEFAULT_OPTIONS = {
|
|
6
6
|
order: [
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_helper_route_index = require("../../helper/route/index.js");
|
|
3
|
+
//#region src/middleware/mount/index.ts
|
|
4
|
+
const defaultReplaceRequest = (c) => {
|
|
5
|
+
const pathPrefix = require_helper_route_index.routePath(c).replace(/\/\*$/, "");
|
|
6
|
+
const url = new URL(c.req.raw.url);
|
|
7
|
+
url.pathname = c.req.path.slice(pathPrefix.length) || "/";
|
|
8
|
+
return new Request(url, c.req.raw);
|
|
9
|
+
};
|
|
10
|
+
const defaultGetOptions = (c) => {
|
|
11
|
+
let executionContext = void 0;
|
|
12
|
+
try {
|
|
13
|
+
executionContext = c.executionCtx;
|
|
14
|
+
} catch {}
|
|
15
|
+
return [c.env, executionContext];
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* `mount()` allows you to mount applications built with other frameworks into your Hono application.
|
|
19
|
+
*
|
|
20
|
+
* @see {@link https://hono.dev/docs/api/hono#mount}
|
|
21
|
+
*
|
|
22
|
+
* @param {Function} applicationHandler - other Request Handler
|
|
23
|
+
* @param {MountOptions} [options] - options of `mount()`
|
|
24
|
+
* @returns {MiddlewareHandler} handler to register with `app.all()`
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```ts
|
|
28
|
+
* import { Router as IttyRouter } from 'itty-router'
|
|
29
|
+
* import { Hono } from 'hono'
|
|
30
|
+
* import { mount } from 'hono/mount'
|
|
31
|
+
* // Create itty-router application
|
|
32
|
+
* const ittyRouter = IttyRouter()
|
|
33
|
+
* // GET /itty-router/hello
|
|
34
|
+
* ittyRouter.get('/hello', () => new Response('Hello from itty-router'))
|
|
35
|
+
*
|
|
36
|
+
* const app = new Hono()
|
|
37
|
+
* app.all('/itty-router/*', mount(ittyRouter.handle))
|
|
38
|
+
* ```
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```ts
|
|
42
|
+
* const app = new Hono()
|
|
43
|
+
* // Send the request to another application without modification.
|
|
44
|
+
* app.all('/app/*', mount(anotherApp, {
|
|
45
|
+
* replaceRequest: (req) => req,
|
|
46
|
+
* }))
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
const mount = (applicationHandler, options) => {
|
|
50
|
+
let replaceRequest;
|
|
51
|
+
let optionHandler;
|
|
52
|
+
if (options) {
|
|
53
|
+
if (typeof options === "function") optionHandler = options;
|
|
54
|
+
else {
|
|
55
|
+
optionHandler = options.optionHandler;
|
|
56
|
+
if (options.replaceRequest === false) replaceRequest = (request) => request;
|
|
57
|
+
else replaceRequest = options.replaceRequest;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
const getOptions = optionHandler ? (c) => {
|
|
61
|
+
const options = optionHandler(c);
|
|
62
|
+
return Array.isArray(options) ? options : [options];
|
|
63
|
+
} : defaultGetOptions;
|
|
64
|
+
return async (c, next) => {
|
|
65
|
+
const res = await applicationHandler(replaceRequest ? replaceRequest(c.req.raw) : defaultReplaceRequest(c), ...getOptions(c));
|
|
66
|
+
if (res) return res;
|
|
67
|
+
await next();
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
//#endregion
|
|
71
|
+
exports.mount = mount;
|