@astrale-os/kernel-protocol 0.5.0-beta.71 → 0.5.0-beta.73
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.ts +0 -2
- package/dist/index.js +0 -2
- package/dist/invocation/binding-codecs.d.ts +3 -2
- package/dist/invocation/delegate.js +1 -2
- package/dist/invocation/index.d.ts +0 -3
- package/dist/invocation/index.js +0 -2
- package/dist/invocation/redirect.d.ts +3 -8
- package/dist/invocation/redirect.js +4 -4
- package/dist/invocation/routing.d.ts +8 -12
- package/dist/invocation/routing.js +7 -22
- package/dist/invocation/stale-route.d.ts +3 -3
- package/dist/release/bindings/index.d.ts +1 -1
- package/dist/release/bindings/view.d.ts +0 -5
- package/dist/release/bindings/view.js +2 -96
- package/dist/release/bundle-admission.js +0 -6
- package/dist/release/delivery/index.d.ts +1 -2
- package/dist/release/delivery/index.js +1 -2
- package/dist/release/delivery/request.d.ts +2 -7
- package/dist/release/delivery/request.js +1 -10
- package/dist/release/index.d.ts +2 -6
- package/dist/release/index.js +0 -4
- package/dist/release/manifest.d.ts +2 -6
- package/dist/release/manifest.js +12 -56
- package/dist/release/release.js +2 -0
- package/dist/release/requirements.d.ts +1 -1
- package/dist/release/requirements.js +1 -1
- package/dist/release/served.d.ts +2 -1
- package/dist/release/served.js +1 -10
- package/dist/routes/compiler.js +1 -2
- package/dist/routes/credential.d.ts +0 -1
- package/dist/routes/credential.js +0 -3
- package/dist/routes/index.d.ts +0 -3
- package/dist/routes/index.js +0 -3
- package/dist/routes/request.d.ts +2 -2
- package/dist/routes/reservation.d.ts +2 -2
- package/dist/routes/reservation.js +8 -9
- package/dist/routes/routing.d.ts +4 -16
- package/dist/routes/routing.js +5 -11
- package/dist/routes/template.d.ts +0 -1
- package/dist/routes/template.js +0 -3
- package/dist/runtime/artifact.d.ts +2 -3
- package/dist/runtime/artifact.js +7 -17
- package/dist/runtime/index.d.ts +1 -1
- package/dist/runtime/index.js +1 -1
- package/dist/schema/installation/codec.d.ts +1 -6
- package/dist/schema/installation/codec.js +2 -6
- package/dist/schema/installation/introspection/codec.d.ts +2 -11
- package/dist/schema/installation/introspection/codec.js +20 -38
- package/dist/schema/installation/introspection/result.d.ts +9 -36
- package/package.json +4 -88
- package/dist/invocation/legacy/delegate.d.ts +0 -17
- package/dist/invocation/legacy/delegate.js +0 -37
- package/dist/invocation/legacy/index.d.ts +0 -29
- package/dist/invocation/legacy/index.js +0 -28
- package/dist/invocation/legacy/route.d.ts +0 -14
- package/dist/invocation/legacy/route.js +0 -25
- package/dist/invocation/legacy/via.d.ts +0 -30
- package/dist/invocation/legacy/via.js +0 -15
- package/dist/release/legacy/bindings.d.ts +0 -14
- package/dist/release/legacy/bindings.js +0 -11
- package/dist/release/legacy/bundle-admission.d.ts +0 -6
- package/dist/release/legacy/bundle-admission.js +0 -10
- package/dist/release/legacy/bundle-evidence.d.ts +0 -8
- package/dist/release/legacy/bundle-evidence.js +0 -11
- package/dist/release/legacy/bundle.d.ts +0 -24
- package/dist/release/legacy/bundle.js +0 -31
- package/dist/release/legacy/delivery/attestation.d.ts +0 -6
- package/dist/release/legacy/delivery/attestation.js +0 -1
- package/dist/release/legacy/delivery/claims.d.ts +0 -25
- package/dist/release/legacy/delivery/claims.js +0 -66
- package/dist/release/legacy/delivery/delivery.d.ts +0 -18
- package/dist/release/legacy/delivery/delivery.js +0 -33
- package/dist/release/legacy/delivery/error.d.ts +0 -16
- package/dist/release/legacy/delivery/error.js +0 -6
- package/dist/release/legacy/delivery/index.d.ts +0 -13
- package/dist/release/legacy/delivery/index.js +0 -13
- package/dist/release/legacy/delivery/limits.d.ts +0 -21
- package/dist/release/legacy/delivery/limits.js +0 -22
- package/dist/release/legacy/delivery/request.d.ts +0 -26
- package/dist/release/legacy/delivery/request.js +0 -57
- package/dist/release/legacy/delivery-declaration.d.ts +0 -9
- package/dist/release/legacy/delivery-declaration.js +0 -11
- package/dist/release/legacy/error.d.ts +0 -26
- package/dist/release/legacy/error.js +0 -114
- package/dist/release/legacy/etag.d.ts +0 -12
- package/dist/release/legacy/etag.js +0 -14
- package/dist/release/legacy/index.d.ts +0 -75
- package/dist/release/legacy/index.js +0 -15
- package/dist/release/legacy/profiles.d.ts +0 -23
- package/dist/release/legacy/profiles.js +0 -36
- package/dist/release/legacy/projection.d.ts +0 -13
- package/dist/release/legacy/projection.js +0 -25
- package/dist/release/legacy/publication.d.ts +0 -90
- package/dist/release/legacy/publication.js +0 -124
- package/dist/release/legacy/reference.d.ts +0 -47
- package/dist/release/legacy/reference.js +0 -92
- package/dist/release/legacy/requirements.d.ts +0 -30
- package/dist/release/legacy/requirements.js +0 -20
- package/dist/routes/legacy/index.d.ts +0 -29
- package/dist/routes/legacy/index.js +0 -29
- package/dist/routes/legacy/routing.d.ts +0 -24
- package/dist/routes/legacy/routing.js +0 -45
- package/dist/routes/legacy/table.d.ts +0 -34
- package/dist/routes/legacy/table.js +0 -50
- package/dist/schema/installation/legacy/index.d.ts +0 -39
- package/dist/schema/installation/legacy/index.js +0 -39
- package/dist/schema/installation/legacy/installation.d.ts +0 -9
- package/dist/schema/installation/legacy/installation.js +0 -28
- package/dist/schema/installation/legacy/introspection.d.ts +0 -10
- package/dist/schema/installation/legacy/introspection.js +0 -70
- package/dist/schema/installation/legacy/msgpack.d.ts +0 -1
- package/dist/schema/installation/legacy/msgpack.js +0 -143
package/dist/index.d.ts
CHANGED
|
@@ -2,8 +2,6 @@ export * as artifact from './artifact/index.js';
|
|
|
2
2
|
export * as invocation from './invocation/index.js';
|
|
3
3
|
export * as codecs from './codecs/index.js';
|
|
4
4
|
export * as errors from './errors/index.js';
|
|
5
|
-
/** @deprecated Use `release`; Publication v2/v3 remains available under `release.legacy`. */
|
|
6
|
-
export * as publication from './release/legacy/index.js';
|
|
7
5
|
export * as release from './release/index.js';
|
|
8
6
|
export * as schema from './schema/index.js';
|
|
9
7
|
export * as routes from './routes/index.js';
|
package/dist/index.js
CHANGED
|
@@ -2,8 +2,6 @@ export * as artifact from './artifact/index.js';
|
|
|
2
2
|
export * as invocation from './invocation/index.js';
|
|
3
3
|
export * as codecs from './codecs/index.js';
|
|
4
4
|
export * as errors from './errors/index.js';
|
|
5
|
-
/** @deprecated Use `release`; Publication v2/v3 remains available under `release.legacy`. */
|
|
6
|
-
export * as publication from './release/legacy/index.js';
|
|
7
5
|
export * as release from './release/index.js';
|
|
8
6
|
export * as schema from './schema/index.js';
|
|
9
7
|
export * as routes from './routes/index.js';
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import type { Codec } from '../codecs/codec.js';
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
type CodecProfile = 'json';
|
|
3
|
+
interface SupportedCodec {
|
|
4
4
|
readonly codec: Codec;
|
|
5
5
|
readonly profile: CodecProfile;
|
|
6
6
|
}
|
|
7
7
|
export declare function codecProfile(codec: Codec): CodecProfile | undefined;
|
|
8
8
|
export declare function admitSupportedCodecs(supported: readonly Codec[]): readonly SupportedCodec[];
|
|
9
|
+
export {};
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { exactDataObject, exactFields, invalid, required } from './admission.js';
|
|
2
|
-
import { withoutSelfAttenuation } from './legacy/delegate.js';
|
|
3
2
|
const FIELDS = new Set(['ttlSeconds']);
|
|
4
3
|
export function acceptDelegate(input) {
|
|
5
|
-
const object =
|
|
4
|
+
const object = exactDataObject(input, 'delegate');
|
|
6
5
|
exactFields(object, FIELDS, 'delegate');
|
|
7
6
|
required(object, ['ttlSeconds'], 'delegate');
|
|
8
7
|
if (!Number.isSafeInteger(object.ttlSeconds) || object.ttlSeconds < 1) {
|
|
@@ -5,9 +5,6 @@ export { acceptIdempotencyKey, HTTP_IDEMPOTENCY_KEY, MAXIMUM_IDEMPOTENCY_KEY_LEN
|
|
|
5
5
|
export { acceptInvocationId, InvocationError, MAXIMUM_INVOCATION_ID_LENGTH, sameInvocationId, type InvocationId, } from './identity.js';
|
|
6
6
|
export * as http from './http/index.js';
|
|
7
7
|
export { acceptDelegate, type Delegate } from './delegate.js';
|
|
8
|
-
export type { PublicationBindingInput, PublicationVia } from './legacy/index.js';
|
|
9
|
-
/** @deprecated The legacy routed witness every Kernel emits until the breaking release (AM-1). */
|
|
10
|
-
export * as legacy from './legacy/index.js';
|
|
11
8
|
export { decodeMiss, miss, type Miss } from './miss.js';
|
|
12
9
|
export { acceptRoute, acceptRedirection, decodeRedirectResponse, remoteRoute, type RemoteBindingInput, type Redirection, type RedirectResponse, type Route, } from './redirect.js';
|
|
13
10
|
export { decodeRequest, type Request } from './request.js';
|
package/dist/invocation/index.js
CHANGED
|
@@ -5,8 +5,6 @@ export { acceptIdempotencyKey, HTTP_IDEMPOTENCY_KEY, MAXIMUM_IDEMPOTENCY_KEY_LEN
|
|
|
5
5
|
export { acceptInvocationId, InvocationError, MAXIMUM_INVOCATION_ID_LENGTH, sameInvocationId, } from './identity.js';
|
|
6
6
|
export * as http from './http/index.js';
|
|
7
7
|
export { acceptDelegate } from './delegate.js';
|
|
8
|
-
/** @deprecated The legacy routed witness every Kernel emits until the breaking release (AM-1). */
|
|
9
|
-
export * as legacy from './legacy/index.js';
|
|
10
8
|
export { decodeMiss, miss } from './miss.js';
|
|
11
9
|
export { acceptRoute, acceptRedirection, decodeRedirectResponse, remoteRoute, } from './redirect.js';
|
|
12
10
|
export { decodeRequest } from './request.js';
|
|
@@ -4,17 +4,12 @@ import type { InvocationEndpoints } from '../release/bindings/invocation.js';
|
|
|
4
4
|
import type { ReleaseDigest } from '../release/digest.js';
|
|
5
5
|
import type { RequestId } from './correlation.js';
|
|
6
6
|
import type { InvocationId } from './identity.js';
|
|
7
|
-
import type { PublicationVia } from './legacy/via.js';
|
|
8
7
|
import type { Via } from './routing.js';
|
|
9
8
|
import type { Trace } from './trace.js';
|
|
10
9
|
export interface Route {
|
|
11
10
|
readonly endpoint: InvocationEndpoints;
|
|
12
|
-
/**
|
|
13
|
-
|
|
14
|
-
* pins and the v3 projection of v4 pins); successor: `Via`, emitted by the breaking release
|
|
15
|
-
* (AM-1).
|
|
16
|
-
*/
|
|
17
|
-
readonly via: Via | PublicationVia;
|
|
11
|
+
/** Routed witness of the exact installed release. */
|
|
12
|
+
readonly via: Via;
|
|
18
13
|
}
|
|
19
14
|
export interface Redirection {
|
|
20
15
|
readonly route: Route;
|
|
@@ -37,7 +32,7 @@ export interface RemoteBindingInput {
|
|
|
37
32
|
readonly release: ReleaseDigest;
|
|
38
33
|
}
|
|
39
34
|
export declare function acceptRoute(input: unknown): Route;
|
|
40
|
-
/** Project
|
|
35
|
+
/** Project one installed release binding into its routed witness. */
|
|
41
36
|
export declare function remoteRoute(origin: Key.Origin, binding: RemoteBindingInput, issuer: IssuerId): Route;
|
|
42
37
|
export declare function acceptRedirection(input: unknown): Redirection;
|
|
43
38
|
export declare function decodeRedirectResponse(input: unknown): RedirectResponse;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { acceptInvocationEndpoints } from '../release/
|
|
2
|
-
import {
|
|
1
|
+
import { acceptInvocationEndpoints } from '../release/bindings/index.js';
|
|
2
|
+
import { ReleaseError } from '../release/error.js';
|
|
3
3
|
import { exactFields, invalid, invocation, portableObject, requestId, required, string, } from './admission.js';
|
|
4
4
|
import { acceptVia } from './routing.js';
|
|
5
5
|
import { admitTrace } from './trace.js';
|
|
@@ -15,13 +15,13 @@ export function acceptRoute(input) {
|
|
|
15
15
|
return Object.freeze({ endpoint: acceptInvocationEndpoints(object.endpoint), via });
|
|
16
16
|
}
|
|
17
17
|
catch (cause) {
|
|
18
|
-
if (cause instanceof
|
|
18
|
+
if (cause instanceof ReleaseError) {
|
|
19
19
|
return invalid(`route is invalid: ${cause.message}`);
|
|
20
20
|
}
|
|
21
21
|
throw cause;
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
|
-
/** Project
|
|
24
|
+
/** Project one installed release binding into its routed witness. */
|
|
25
25
|
export function remoteRoute(origin, binding, issuer) {
|
|
26
26
|
return acceptRoute({
|
|
27
27
|
endpoint: binding.endpoint,
|
|
@@ -3,7 +3,6 @@ import type { Revision } from '@astrale-os/kernel-dsl/v1/addressing';
|
|
|
3
3
|
import type { Object as ValueObject } from '@astrale-os/kernel-dsl/value';
|
|
4
4
|
import type { Sha256Digest } from '../release/digest.js';
|
|
5
5
|
import type { ReleaseRef } from '../release/reference.js';
|
|
6
|
-
import type { PublicationVia } from './legacy/via.js';
|
|
7
6
|
/** Routed witness of one installed release: the Kernel routed this call to that exact release. */
|
|
8
7
|
export interface Via {
|
|
9
8
|
readonly kind: 'via';
|
|
@@ -14,15 +13,12 @@ export interface Refresh {
|
|
|
14
13
|
readonly kind: 'refresh';
|
|
15
14
|
readonly stale: Sha256Digest;
|
|
16
15
|
}
|
|
17
|
-
/** A received `Via` names
|
|
18
|
-
export type Routing = Via |
|
|
16
|
+
/** A received `Via` names one exact `ReleaseRef`. */
|
|
17
|
+
export type Routing = Via | Refresh;
|
|
19
18
|
export declare function acceptRouting(input: unknown): Routing;
|
|
20
|
-
/** Admit one routed witness carrying
|
|
21
|
-
export declare function acceptVia(object: ValueObject, label: string): Via
|
|
22
|
-
/** Schema revision of the release
|
|
23
|
-
export declare function routedRevision(via: Via
|
|
24
|
-
/**
|
|
25
|
-
|
|
26
|
-
* Publication ETag of a legacy `PublicationVia`.
|
|
27
|
-
*/
|
|
28
|
-
export declare function routedDigest(via: Via | PublicationVia): Sha256Digest;
|
|
19
|
+
/** Admit one routed witness carrying one exact `release`. */
|
|
20
|
+
export declare function acceptVia(object: ValueObject, label: string): Via;
|
|
21
|
+
/** Schema revision of the release the witness routed the call to. */
|
|
22
|
+
export declare function routedRevision(via: Via): Revision;
|
|
23
|
+
/** Digest of the release the witness routed this call to. */
|
|
24
|
+
export declare function routedDigest(via: Via): Sha256Digest;
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { ReleaseError } from '../release/error.js';
|
|
2
2
|
import { acceptReference } from '../release/reference.js';
|
|
3
3
|
import { digest, exactFields, invalid, issuerId, portableObject, required } from './admission.js';
|
|
4
|
-
|
|
5
|
-
const VIA_FIELDS = new Set(['kind', 'release', 'publication', 'issuer']);
|
|
4
|
+
const VIA_FIELDS = new Set(['kind', 'release', 'issuer']);
|
|
6
5
|
const REFRESH_FIELDS = new Set(['kind', 'stale']);
|
|
7
6
|
export function acceptRouting(input) {
|
|
8
7
|
const object = portableObject(input, 'routing');
|
|
@@ -18,39 +17,25 @@ export function acceptRouting(input) {
|
|
|
18
17
|
}
|
|
19
18
|
return invalid('routing.kind must be "via" or "refresh"');
|
|
20
19
|
}
|
|
21
|
-
/** Admit one routed witness carrying
|
|
20
|
+
/** Admit one routed witness carrying one exact `release`. */
|
|
22
21
|
export function acceptVia(object, label) {
|
|
23
22
|
exactFields(object, VIA_FIELDS, label);
|
|
24
23
|
if (object.kind !== 'via')
|
|
25
24
|
invalid(`${label}.kind must be "via"`);
|
|
26
|
-
|
|
27
|
-
if (hasRelease === Object.hasOwn(object, 'publication')) {
|
|
28
|
-
invalid(`${label} must contain exactly one of release or publication`);
|
|
29
|
-
}
|
|
30
|
-
required(object, ['issuer'], label);
|
|
31
|
-
if (!hasRelease) {
|
|
32
|
-
return Object.freeze({
|
|
33
|
-
kind: 'via',
|
|
34
|
-
publication: acceptPublicationReference(object.publication, `${label}.publication`),
|
|
35
|
-
issuer: issuerId(object.issuer, `${label}.issuer`),
|
|
36
|
-
});
|
|
37
|
-
}
|
|
25
|
+
required(object, ['release', 'issuer'], label);
|
|
38
26
|
return Object.freeze({
|
|
39
27
|
kind: 'via',
|
|
40
28
|
release: acceptReleaseReference(object.release, `${label}.release`),
|
|
41
29
|
issuer: issuerId(object.issuer, `${label}.issuer`),
|
|
42
30
|
});
|
|
43
31
|
}
|
|
44
|
-
/** Schema revision of the release
|
|
32
|
+
/** Schema revision of the release the witness routed the call to. */
|
|
45
33
|
export function routedRevision(via) {
|
|
46
|
-
return
|
|
34
|
+
return via.release.revision;
|
|
47
35
|
}
|
|
48
|
-
/**
|
|
49
|
-
* Digest designating what the witness routed the call to: the release digest of a `Via`, the
|
|
50
|
-
* Publication ETag of a legacy `PublicationVia`.
|
|
51
|
-
*/
|
|
36
|
+
/** Digest of the release the witness routed this call to. */
|
|
52
37
|
export function routedDigest(via) {
|
|
53
|
-
return
|
|
38
|
+
return via.release.digest;
|
|
54
39
|
}
|
|
55
40
|
function acceptReleaseReference(input, label) {
|
|
56
41
|
try {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ReleaseDigest } from '../release/digest.js';
|
|
2
2
|
import type { RequestId } from './correlation.js';
|
|
3
3
|
import type { InvocationId } from './identity.js';
|
|
4
4
|
/** Reserved pre-handler routing control; never an application ErrorResponse. */
|
|
@@ -6,7 +6,7 @@ export interface Stale {
|
|
|
6
6
|
readonly kind: 'stale';
|
|
7
7
|
readonly requestId: RequestId;
|
|
8
8
|
readonly invocation: InvocationId;
|
|
9
|
-
readonly current:
|
|
9
|
+
readonly current: ReleaseDigest;
|
|
10
10
|
}
|
|
11
11
|
export declare function decodeStale(input: unknown): Stale;
|
|
12
|
-
export declare function stale(requestId: RequestId, assigned: InvocationId, current:
|
|
12
|
+
export declare function stale(requestId: RequestId, assigned: InvocationId, current: ReleaseDigest): Stale;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { admitCallableBinding, admitCallableKey, type CallableBinding } from './callable.js';
|
|
2
2
|
export { acceptInvocationEndpoints, type InvocationEndpoints } from './invocation.js';
|
|
3
|
-
export { admitViewBinding, type
|
|
3
|
+
export { admitViewBinding, type ViewBinding } from './view.js';
|
|
@@ -4,13 +4,8 @@ export interface ViewBinding {
|
|
|
4
4
|
readonly view: Key.View;
|
|
5
5
|
readonly href: string;
|
|
6
6
|
readonly handshake: 'shell' | 'none';
|
|
7
|
-
readonly iframe?: IframeRequirements;
|
|
8
7
|
readonly host?: ViewHostRequirements;
|
|
9
8
|
}
|
|
10
|
-
export interface IframeRequirements {
|
|
11
|
-
readonly sandbox?: readonly string[];
|
|
12
|
-
readonly allow?: readonly string[];
|
|
13
|
-
}
|
|
14
9
|
export declare function admitViewBinding(input: unknown, origin: string): ViewBinding;
|
|
15
10
|
/** Authoring-only normalization used before a release document is sealed. */
|
|
16
11
|
export declare function canonicalizeViewBinding(input: unknown, origin: string): ViewBinding;
|
|
@@ -2,7 +2,6 @@ import { acceptViewHostRequirements, } from '@astrale-os/kernel-core/schema/kern
|
|
|
2
2
|
import { Key } from '@astrale-os/kernel-dsl/v1/addressing';
|
|
3
3
|
import { fail } from '../error.js';
|
|
4
4
|
import { absoluteHttpUrl, exact, record } from '../shape.js';
|
|
5
|
-
const TOKEN = /^[a-z][a-z0-9-]*$/u;
|
|
6
5
|
export function admitViewBinding(input, origin) {
|
|
7
6
|
return readViewBinding(input, origin, false);
|
|
8
7
|
}
|
|
@@ -12,7 +11,7 @@ export function canonicalizeViewBinding(input, origin) {
|
|
|
12
11
|
}
|
|
13
12
|
function readViewBinding(input, origin, canonicalize) {
|
|
14
13
|
const value = record(input, 'RELEASE_VIEW_INVALID', 'Release View binding is invalid.');
|
|
15
|
-
exact(value, ['view', 'href', 'handshake', '
|
|
14
|
+
exact(value, ['view', 'href', 'handshake', 'host'], 'RELEASE_VIEW_INVALID');
|
|
16
15
|
let view;
|
|
17
16
|
try {
|
|
18
17
|
view = Key(String(value.view));
|
|
@@ -29,7 +28,6 @@ function readViewBinding(input, origin, canonicalize) {
|
|
|
29
28
|
if (value.handshake !== 'shell' && value.handshake !== 'none') {
|
|
30
29
|
fail('RELEASE_VIEW_INVALID', 'View handshake is invalid.');
|
|
31
30
|
}
|
|
32
|
-
const iframe = admitIframeRequirements(dataValue(value, 'iframe'), value.handshake, canonicalize);
|
|
33
31
|
let host;
|
|
34
32
|
try {
|
|
35
33
|
host = acceptViewHostRequirements(dataValue(value, 'host'), value.handshake, canonicalize);
|
|
@@ -43,106 +41,14 @@ function readViewBinding(input, origin, canonicalize) {
|
|
|
43
41
|
view,
|
|
44
42
|
href: absoluteHttpUrl(value.href, true, 'RELEASE_VIEW_INVALID'),
|
|
45
43
|
handshake: value.handshake,
|
|
46
|
-
...(iframe === undefined ? {} : { iframe }),
|
|
47
44
|
...(host === undefined ? {} : { host }),
|
|
48
45
|
});
|
|
49
46
|
}
|
|
50
|
-
function admitIframeRequirements(input, handshake, canonicalize) {
|
|
51
|
-
if (input === undefined)
|
|
52
|
-
return undefined;
|
|
53
|
-
const value = plainRecord(input);
|
|
54
|
-
exactOwnKeys(value, ['sandbox', 'allow']);
|
|
55
|
-
if (!canonicalize && (!Object.hasOwn(value, 'sandbox') || !Object.hasOwn(value, 'allow'))) {
|
|
56
|
-
invalid();
|
|
57
|
-
}
|
|
58
|
-
const sandbox = tokens(dataValue(value, 'sandbox'), canonicalize);
|
|
59
|
-
const allow = tokens(dataValue(value, 'allow'), canonicalize);
|
|
60
|
-
assertRelationships(sandbox);
|
|
61
|
-
const baselineSandbox = handshake === 'shell' ? ['allow-same-origin', 'allow-scripts'] : ['allow-scripts'];
|
|
62
|
-
const baselineAllow = handshake === 'shell' ? ['clipboard-write'] : [];
|
|
63
|
-
if (!canonicalize &&
|
|
64
|
-
(sandbox.some((token) => baselineSandbox.includes(token)) ||
|
|
65
|
-
allow.some((feature) => baselineAllow.includes(feature)))) {
|
|
66
|
-
invalid();
|
|
67
|
-
}
|
|
68
|
-
const canonicalSandbox = canonicalize
|
|
69
|
-
? sandbox.filter((token) => !baselineSandbox.includes(token))
|
|
70
|
-
: sandbox;
|
|
71
|
-
const canonicalAllow = canonicalize
|
|
72
|
-
? allow.filter((feature) => !baselineAllow.includes(feature))
|
|
73
|
-
: allow;
|
|
74
|
-
if (!canonicalize && canonicalSandbox.length === 0 && canonicalAllow.length === 0)
|
|
75
|
-
invalid();
|
|
76
|
-
if (canonicalSandbox.length === 0 && canonicalAllow.length === 0)
|
|
77
|
-
return undefined;
|
|
78
|
-
return Object.freeze({
|
|
79
|
-
sandbox: Object.freeze(canonicalSandbox),
|
|
80
|
-
allow: Object.freeze(canonicalAllow),
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
function plainRecord(input) {
|
|
84
|
-
if (input === null || typeof input !== 'object' || Array.isArray(input))
|
|
85
|
-
invalid();
|
|
86
|
-
const prototype = Object.getPrototypeOf(input);
|
|
87
|
-
if (prototype !== Object.prototype && prototype !== null)
|
|
88
|
-
invalid();
|
|
89
|
-
return input;
|
|
90
|
-
}
|
|
91
|
-
function exactOwnKeys(input, allowed) {
|
|
92
|
-
const keys = new Set(allowed);
|
|
93
|
-
if (Reflect.ownKeys(input).some((key) => typeof key !== 'string' || !keys.has(key)))
|
|
94
|
-
invalid();
|
|
95
|
-
}
|
|
96
47
|
function dataValue(input, key) {
|
|
97
48
|
const descriptor = Object.getOwnPropertyDescriptor(input, key);
|
|
98
49
|
if (descriptor === undefined)
|
|
99
50
|
return undefined;
|
|
100
51
|
if (!('value' in descriptor))
|
|
101
|
-
|
|
52
|
+
fail('RELEASE_VIEW_INVALID', 'View requirements must be data fields.');
|
|
102
53
|
return descriptor.value;
|
|
103
54
|
}
|
|
104
|
-
function tokens(input, canonicalize) {
|
|
105
|
-
if (input === undefined)
|
|
106
|
-
return [];
|
|
107
|
-
if (!Array.isArray(input))
|
|
108
|
-
invalid();
|
|
109
|
-
const descriptors = Object.getOwnPropertyDescriptors(input);
|
|
110
|
-
const values = [];
|
|
111
|
-
for (let index = 0; index < input.length; index += 1) {
|
|
112
|
-
const descriptor = descriptors[String(index)];
|
|
113
|
-
if (descriptor === undefined || !('value' in descriptor))
|
|
114
|
-
invalid();
|
|
115
|
-
if (typeof descriptor.value !== 'string' || !TOKEN.test(descriptor.value))
|
|
116
|
-
invalid();
|
|
117
|
-
values.push(descriptor.value);
|
|
118
|
-
}
|
|
119
|
-
for (const key of Reflect.ownKeys(descriptors)) {
|
|
120
|
-
if (key === 'length')
|
|
121
|
-
continue;
|
|
122
|
-
if (typeof key !== 'string' || !/^(0|[1-9][0-9]*)$/u.test(key) || Number(key) >= input.length) {
|
|
123
|
-
invalid();
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
if (canonicalize)
|
|
127
|
-
return [...new Set(values)].sort();
|
|
128
|
-
for (let index = 1; index < values.length; index += 1) {
|
|
129
|
-
if (values[index - 1] >= values[index])
|
|
130
|
-
invalid();
|
|
131
|
-
}
|
|
132
|
-
return values;
|
|
133
|
-
}
|
|
134
|
-
function assertRelationships(sandbox) {
|
|
135
|
-
const tokens = new Set(sandbox);
|
|
136
|
-
if (tokens.has('allow-popups-to-escape-sandbox') && !tokens.has('allow-popups'))
|
|
137
|
-
invalid();
|
|
138
|
-
if (tokens.has('allow-top-navigation') && tokens.has('allow-top-navigation-by-user-activation')) {
|
|
139
|
-
invalid();
|
|
140
|
-
}
|
|
141
|
-
if (tokens.has('allow-top-navigation-to-custom-protocols') &&
|
|
142
|
-
(tokens.has('allow-top-navigation') || tokens.has('allow-popups'))) {
|
|
143
|
-
invalid();
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
function invalid() {
|
|
147
|
-
return fail('RELEASE_VIEW_INVALID', 'View iframe requirements are invalid.');
|
|
148
|
-
}
|
|
@@ -33,12 +33,6 @@ function validateInventory(release, bundle) {
|
|
|
33
33
|
if (boundViews.size !== views.size || [...views].some((key) => !boundViews.has(key))) {
|
|
34
34
|
fail('RELEASE_VIEW_INVALID', 'View bindings must exhaust the root Domain.');
|
|
35
35
|
}
|
|
36
|
-
if (release.manifest?.entrypoint !== undefined &&
|
|
37
|
-
(release.manifest.entrypoint.origin !== root.origin ||
|
|
38
|
-
release.manifest.entrypoint.kind !== 'view' ||
|
|
39
|
-
root.views[release.manifest.entrypoint.name] === undefined)) {
|
|
40
|
-
fail('RELEASE_INVALID', 'Manifest entrypoint does not exist in the root schema.');
|
|
41
|
-
}
|
|
42
36
|
for (const route of release.routes) {
|
|
43
37
|
if (!callables.has(route.callable)) {
|
|
44
38
|
fail('RELEASE_ROUTE_INVALID', `Route ${route.name} names an unknown callable.`);
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Delivery v2: the challenge-bound envelope carrying the exact `DomainRelease` a Kernel fetched at
|
|
3
|
-
* `release.json`, bound to its release digest.
|
|
4
|
-
* discriminated by its `version`.
|
|
3
|
+
* `release.json`, bound to its release digest. Only the version 2 request is admitted.
|
|
5
4
|
*/
|
|
6
5
|
export { type Attestation } from './attestation.js';
|
|
7
6
|
export { acceptClaims, type Claims } from './claims.js';
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Delivery v2: the challenge-bound envelope carrying the exact `DomainRelease` a Kernel fetched at
|
|
3
|
-
* `release.json`, bound to its release digest.
|
|
4
|
-
* discriminated by its `version`.
|
|
3
|
+
* `release.json`, bound to its release digest. Only the version 2 request is admitted.
|
|
5
4
|
*/
|
|
6
5
|
export {} from './attestation.js';
|
|
7
6
|
export { acceptClaims } from './claims.js';
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { type IssuerId } from '@astrale-os/kernel-core/auth/issuer';
|
|
2
2
|
import type { ReleaseDigest } from '../digest.js';
|
|
3
|
-
import { type Request as PublicationRequest } from '../legacy/delivery/request.js';
|
|
4
3
|
/** Exact bearer credential admitted by a Delivery transport boundary; never inside a document. */
|
|
5
4
|
export interface Token {
|
|
6
5
|
readonly kind: 'bearer';
|
|
@@ -13,9 +12,5 @@ export interface Request {
|
|
|
13
12
|
readonly nonce: string;
|
|
14
13
|
readonly release: ReleaseDigest;
|
|
15
14
|
}
|
|
16
|
-
/**
|
|
17
|
-
|
|
18
|
-
* own `version` selects the Delivery version: 2 names a release digest, and the deprecated 1 names
|
|
19
|
-
* the ETag of a v2/v3 Publication fetched at `domain.json`.
|
|
20
|
-
*/
|
|
21
|
-
export declare function acceptRequest(input: unknown): Request | PublicationRequest;
|
|
15
|
+
/** Admit the exact version-two challenge at a Delivery transport boundary. */
|
|
16
|
+
export declare function acceptRequest(input: unknown): Request;
|
|
@@ -1,22 +1,13 @@
|
|
|
1
1
|
import { AuthValueError } from '@astrale-os/kernel-core/auth/error';
|
|
2
2
|
import { accept as acceptIssuer } from '@astrale-os/kernel-core/auth/issuer';
|
|
3
|
-
import { acceptRequest as acceptPublicationRequest, } from '../legacy/delivery/request.js';
|
|
4
3
|
import { fail } from './error.js';
|
|
5
4
|
import { NONCE_MAX_LENGTH, NONCE_MIN_LENGTH } from './limits.js';
|
|
6
5
|
const FIELDS = ['version', 'kernel', 'nonce', 'release'];
|
|
7
|
-
/**
|
|
8
|
-
* Admit the exact request representation accepted by a Delivery transport boundary. The request's
|
|
9
|
-
* own `version` selects the Delivery version: 2 names a release digest, and the deprecated 1 names
|
|
10
|
-
* the ETag of a v2/v3 Publication fetched at `domain.json`.
|
|
11
|
-
*/
|
|
6
|
+
/** Admit the exact version-two challenge at a Delivery transport boundary. */
|
|
12
7
|
export function acceptRequest(input) {
|
|
13
8
|
if (input === null || typeof input !== 'object' || Array.isArray(input)) {
|
|
14
9
|
fail('DELIVERY_REQUEST_INVALID', 'Expected a Delivery request.');
|
|
15
10
|
}
|
|
16
|
-
const version = Object.getOwnPropertyDescriptor(input, 'version');
|
|
17
|
-
if (version !== undefined && 'value' in version && version.value === 1) {
|
|
18
|
-
return acceptPublicationRequest(input);
|
|
19
|
-
}
|
|
20
11
|
const value = {};
|
|
21
12
|
const fields = Reflect.ownKeys(input);
|
|
22
13
|
if (fields.length !== FIELDS.length) {
|
package/dist/release/index.d.ts
CHANGED
|
@@ -9,13 +9,9 @@ export { placeDelivery } from './delivery-declaration.js';
|
|
|
9
9
|
export type { Authentication as DeliveryAuthentication, Endpoint as DeliveryEndpoint, } from './delivery-endpoint.js';
|
|
10
10
|
export type { BuildDigest, ReleaseDigest, Sha256Digest } from './digest.js';
|
|
11
11
|
export { ReleaseError, type ReleaseErrorCode } from './error.js';
|
|
12
|
-
export type {
|
|
12
|
+
export type { Manifest } from './manifest.js';
|
|
13
13
|
export { ClassOperationOrder, admitRequirements, capabilityKeys, validateRequirements, type CapabilityAuthorityRequirements, type CoreCapabilityRequirement, type CapabilityRequirements, type ClassCapabilityRequirement, type ClassOperation, type NonEmpty, type Requirements, } from './requirements.js';
|
|
14
14
|
export type { BodyPick, CredentialSource, HttpMethod, HttpRoute, HttpRouteDeclaration, RouteBody, RouteHeaders, SingleCredentialSource, } from './route.js';
|
|
15
15
|
export type { Schema } from './schema.js';
|
|
16
|
-
export { acceptInvocationEndpoints, type CallableBinding, type
|
|
16
|
+
export { acceptInvocationEndpoints, type CallableBinding, type InvocationEndpoints, type ViewBinding, } from './bindings/index.js';
|
|
17
17
|
export * as delivery from './delivery/index.js';
|
|
18
|
-
/**
|
|
19
|
-
* @deprecated Publication v2/v3 compatibility surface; use `DomainRelease` v4 from this module.
|
|
20
|
-
*/
|
|
21
|
-
export * as legacy from './legacy/index.js';
|
package/dist/release/index.js
CHANGED
|
@@ -8,7 +8,3 @@ export { ReleaseError } from './error.js';
|
|
|
8
8
|
export { ClassOperationOrder, admitRequirements, capabilityKeys, validateRequirements, } from './requirements.js';
|
|
9
9
|
export { acceptInvocationEndpoints, } from './bindings/index.js';
|
|
10
10
|
export * as delivery from './delivery/index.js';
|
|
11
|
-
/**
|
|
12
|
-
* @deprecated Publication v2/v3 compatibility surface; use `DomainRelease` v4 from this module.
|
|
13
|
-
*/
|
|
14
|
-
export * as legacy from './legacy/index.js';
|
|
@@ -1,10 +1,6 @@
|
|
|
1
|
-
import { type ViewRef } from '@astrale-os/kernel-dsl/v1/addressing';
|
|
2
|
-
/** A display name per language, keyed by a BCP 47 language tag in canonical case (`fr`, `pt-BR`). */
|
|
3
|
-
export type LocalizedText = Readonly<Record<string, string>>;
|
|
4
1
|
export interface Manifest {
|
|
5
|
-
/** The application's display name, per language. */
|
|
6
|
-
readonly title?: LocalizedText;
|
|
7
2
|
readonly logo?: string;
|
|
8
|
-
readonly entrypoint?: ViewRef;
|
|
9
3
|
}
|
|
4
|
+
/** The root Schema owns the Domain name and entrypoint in every release. */
|
|
5
|
+
export declare function assertAuthoredManifest(input: unknown): void;
|
|
10
6
|
export declare function admitManifest(input: unknown): Manifest | undefined;
|
package/dist/release/manifest.js
CHANGED
|
@@ -1,66 +1,22 @@
|
|
|
1
|
-
import { acceptDefinitionRef } from '@astrale-os/kernel-dsl/v1/addressing';
|
|
2
1
|
import { fail } from './error.js';
|
|
3
2
|
import { exact, record } from './shape.js';
|
|
4
|
-
/**
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
3
|
+
/** The root Schema owns the Domain name and entrypoint in every release. */
|
|
4
|
+
export function assertAuthoredManifest(input) {
|
|
5
|
+
if (input === null || typeof input !== 'object')
|
|
6
|
+
return;
|
|
7
|
+
for (const removed of ['title', 'entrypoint']) {
|
|
8
|
+
if (Object.hasOwn(input, removed)) {
|
|
9
|
+
fail('RELEASE_INVALID', `Manifest ${removed} is removed: the root schema declares the Domain name and entrypoint.`);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
}
|
|
11
13
|
export function admitManifest(input) {
|
|
12
14
|
if (input === undefined)
|
|
13
15
|
return undefined;
|
|
14
16
|
const value = record(input, 'RELEASE_INVALID', 'Manifest is invalid.');
|
|
15
|
-
exact(value, ['
|
|
16
|
-
const title = value.title === undefined ? undefined : admitTitle(value.title);
|
|
17
|
+
exact(value, ['logo'], 'RELEASE_INVALID');
|
|
17
18
|
if (value.logo !== undefined && typeof value.logo !== 'string') {
|
|
18
19
|
fail('RELEASE_INVALID', 'Manifest logo must be a string.');
|
|
19
20
|
}
|
|
20
|
-
|
|
21
|
-
if (value.entrypoint !== undefined) {
|
|
22
|
-
let ref;
|
|
23
|
-
try {
|
|
24
|
-
ref = acceptDefinitionRef(value.entrypoint);
|
|
25
|
-
}
|
|
26
|
-
catch (cause) {
|
|
27
|
-
return fail('RELEASE_INVALID', 'Manifest entrypoint must be a root View reference.', cause);
|
|
28
|
-
}
|
|
29
|
-
if (ref.kind !== 'view') {
|
|
30
|
-
fail('RELEASE_INVALID', 'Manifest entrypoint must be a root View reference.');
|
|
31
|
-
}
|
|
32
|
-
entrypoint = ref;
|
|
33
|
-
}
|
|
34
|
-
return Object.freeze({
|
|
35
|
-
...(title === undefined ? {} : { title }),
|
|
36
|
-
...(value.logo === undefined ? {} : { logo: value.logo }),
|
|
37
|
-
...(entrypoint === undefined ? {} : { entrypoint }),
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* A release is canonical, so a title is admitted exactly as written or refused: never trimmed,
|
|
42
|
-
* re-cased or truncated, which would make its digest differ from what the author signed.
|
|
43
|
-
*/
|
|
44
|
-
function admitTitle(input) {
|
|
45
|
-
const value = record(input, 'RELEASE_INVALID', 'Manifest title is invalid.');
|
|
46
|
-
const languages = Object.keys(value);
|
|
47
|
-
if (languages.length === 0 || languages.length > MAXIMUM_TITLE_LANGUAGES) {
|
|
48
|
-
fail('RELEASE_INVALID', 'Manifest title must name between 1 and 32 languages.');
|
|
49
|
-
}
|
|
50
|
-
const title = {};
|
|
51
|
-
for (const language of languages) {
|
|
52
|
-
if (!LANGUAGE_TAG.test(language)) {
|
|
53
|
-
fail('RELEASE_INVALID', 'Manifest title languages must be canonical BCP 47 tags.');
|
|
54
|
-
}
|
|
55
|
-
const text = value[language];
|
|
56
|
-
if (typeof text !== 'string' ||
|
|
57
|
-
text.length === 0 ||
|
|
58
|
-
text.length > MAXIMUM_TITLE_LENGTH ||
|
|
59
|
-
text.trim() !== text ||
|
|
60
|
-
CONTROL.test(text)) {
|
|
61
|
-
fail('RELEASE_INVALID', 'Manifest title text must be one trimmed line of 1 to 120 characters.');
|
|
62
|
-
}
|
|
63
|
-
title[language] = text;
|
|
64
|
-
}
|
|
65
|
-
return Object.freeze(title);
|
|
21
|
+
return Object.freeze(value.logo === undefined ? {} : { logo: value.logo });
|
|
66
22
|
}
|
package/dist/release/release.js
CHANGED
|
@@ -3,6 +3,7 @@ import { admitBuild } from './build.js';
|
|
|
3
3
|
import { admitDigest, sha256Hex } from './digest.js';
|
|
4
4
|
import { fail } from './error.js';
|
|
5
5
|
import { servedUrl } from './issuer.js';
|
|
6
|
+
import { assertAuthoredManifest } from './manifest.js';
|
|
6
7
|
import { admitServedContent } from './served.js';
|
|
7
8
|
import { deepFreeze, exact, record } from './shape.js';
|
|
8
9
|
/** Path of the release a deployment serves beneath its serving issuer. */
|
|
@@ -41,6 +42,7 @@ export function digestOf(input) {
|
|
|
41
42
|
export function seal(input) {
|
|
42
43
|
const authored = record(input, 'RELEASE_INVALID', 'Expected release content.');
|
|
43
44
|
exact(authored, CONTENT_FIELDS, 'RELEASE_INVALID');
|
|
45
|
+
assertAuthoredManifest(authored.manifest);
|
|
44
46
|
const canonical = admitContent(admitContent(authored, 'canonicalize'), 'admit');
|
|
45
47
|
return release(canonical, hash(canonical));
|
|
46
48
|
}
|
|
@@ -29,7 +29,7 @@ export interface Requirements {
|
|
|
29
29
|
readonly capabilities: CapabilityRequirements;
|
|
30
30
|
}
|
|
31
31
|
/**
|
|
32
|
-
* Admit the exact closed canonical requirements object
|
|
32
|
+
* Admit the exact closed canonical Release requirements object.
|
|
33
33
|
*/
|
|
34
34
|
export declare function admitRequirements(input: unknown): Requirements;
|
|
35
35
|
/** Bind explicit capability targets to exact functional dependencies in the bundle closure. */
|
|
@@ -17,7 +17,7 @@ export const ClassOperationOrder = Object.freeze([
|
|
|
17
17
|
'delete',
|
|
18
18
|
]);
|
|
19
19
|
/**
|
|
20
|
-
* Admit the exact closed canonical requirements object
|
|
20
|
+
* Admit the exact closed canonical Release requirements object.
|
|
21
21
|
*/
|
|
22
22
|
export function admitRequirements(input) {
|
|
23
23
|
const requirements = record(input, 'RELEASE_INVALID', 'Release requirements are invalid.');
|
package/dist/release/served.d.ts
CHANGED
|
@@ -13,7 +13,7 @@ export interface ServedContent extends ServedRelease {
|
|
|
13
13
|
};
|
|
14
14
|
readonly delivery?: DeliveryEndpoint;
|
|
15
15
|
}
|
|
16
|
-
|
|
16
|
+
interface ServedOptions {
|
|
17
17
|
/** `canonicalize` normalizes authored View bindings before sealing; `admit` requires canonical ones. */
|
|
18
18
|
readonly views: 'canonicalize' | 'admit';
|
|
19
19
|
/** Reads the requirements coordinate of the document version; canonical `core` by default. */
|
|
@@ -24,3 +24,4 @@ export interface ServedOptions {
|
|
|
24
24
|
* these checks in this order, so a document of any version admits exactly the same served content.
|
|
25
25
|
*/
|
|
26
26
|
export declare function admitServedContent(value: Readonly<Record<string, unknown>>, options: ServedOptions): ServedContent;
|
|
27
|
+
export {};
|