@astrale-os/kernel-protocol 0.5.0-beta.70 → 0.5.0-beta.72
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.d.ts +0 -11
- package/dist/invocation/delegate.js +2 -20
- package/dist/invocation/http/index.d.ts +1 -1
- package/dist/invocation/http/index.js +1 -1
- package/dist/invocation/http/request.d.ts +2 -0
- package/dist/invocation/http/request.js +8 -0
- 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 +1 -5
- package/dist/release/index.js +0 -4
- package/dist/release/manifest.d.ts +2 -2
- package/dist/release/manifest.js +12 -20
- 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/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
|
@@ -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 {};
|
package/dist/release/served.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { patterns } from '@astrale-os/kernel-dsl/v1/addressing';
|
|
2
2
|
import { admitCallableBinding, admitViewBinding } from './bindings/index.js';
|
|
3
3
|
import { canonicalizeViewBinding } from './bindings/view.js';
|
|
4
4
|
import { admitEndpoint as admitDeliveryEndpoint } from './delivery-endpoint.js';
|
|
@@ -42,15 +42,6 @@ export function admitServedContent(value, options) {
|
|
|
42
42
|
fail('RELEASE_ROUTE_INVALID', `Callable ${callable} has more than one default route.`);
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
|
-
if (manifest?.entrypoint !== undefined) {
|
|
46
|
-
if (manifest.entrypoint.origin !== origin) {
|
|
47
|
-
fail('RELEASE_VIEW_INVALID', 'Manifest entrypoint must belong to the root origin.');
|
|
48
|
-
}
|
|
49
|
-
const key = Key.of(manifest.entrypoint);
|
|
50
|
-
if (!views.some(({ view }) => view === key)) {
|
|
51
|
-
fail('RELEASE_VIEW_INVALID', 'Manifest entrypoint must have a published View binding.');
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
45
|
const delivery = admitDeliveryEndpoint(value.delivery, schema.bundle.href);
|
|
55
46
|
return {
|
|
56
47
|
origin,
|
package/dist/routes/compiler.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { isBinaryInput } from '@astrale-os/kernel-dsl/v1/language';
|
|
2
|
-
import { withPublicationError } from '../release/legacy/error.js';
|
|
3
2
|
import { admitRouteDeclaration } from '../release/route.js';
|
|
4
3
|
import { rejectCollisions } from './collision.js';
|
|
5
4
|
import { fail } from './error.js';
|
|
@@ -10,7 +9,7 @@ export function compile(input) {
|
|
|
10
9
|
if (input === null || typeof input !== 'object' || !Array.isArray(input.routes)) {
|
|
11
10
|
throw new TypeError('Route compilation input is invalid.');
|
|
12
11
|
}
|
|
13
|
-
const authored = input.routes.map((entry) =>
|
|
12
|
+
const authored = input.routes.map((entry) => admitRouteDeclaration(entry, input.domain.origin));
|
|
14
13
|
const entries = authored.map((declaration) => {
|
|
15
14
|
const meaning = input.domain.callable(declaration.callable);
|
|
16
15
|
if (meaning === undefined || (isMethod(meaning) && !meaning.executable)) {
|
|
@@ -10,7 +10,6 @@ export interface LocatedCredential {
|
|
|
10
10
|
readonly value: string;
|
|
11
11
|
readonly in: SingleCredentialSource['in'];
|
|
12
12
|
}
|
|
13
|
-
export declare function readCredential(entry: Route, url: URL, headers: Record<string, string>): string | undefined;
|
|
14
13
|
/**
|
|
15
14
|
* Read the request credential and report which declared channel supplied it. A `cookie` channel is
|
|
16
15
|
* ambient (the browser attaches it automatically), which the Server uses to decide CSRF defense; a
|
|
@@ -51,9 +51,6 @@ export function withoutCredentialHeaders(entry, input) {
|
|
|
51
51
|
}
|
|
52
52
|
return output;
|
|
53
53
|
}
|
|
54
|
-
export function readCredential(entry, url, headers) {
|
|
55
|
-
return locateCredential(entry, url, headers)?.value;
|
|
56
|
-
}
|
|
57
54
|
/**
|
|
58
55
|
* Read the request credential and report which declared channel supplied it. A `cookie` channel is
|
|
59
56
|
* ambient (the browser attaches it automatically), which the Server uses to decide CSRF defense; a
|
package/dist/routes/index.d.ts
CHANGED
|
@@ -17,6 +17,3 @@ export { decodeRouting, decodeMiss, decodeStale, HTTP_ROUTE_DIGEST, HTTP_ROUTE_I
|
|
|
17
17
|
export { select } from './select.js';
|
|
18
18
|
export { decodeStreamFrame, encodeStreamFrame, STREAM_MEDIA_TYPE, type StreamFrame, } from './stream.js';
|
|
19
19
|
export { templatesOverlap } from './template.js';
|
|
20
|
-
/** @deprecated Native routes of a v3-input destination; use the release-bound Table and decoders. */
|
|
21
|
-
export * as legacy from './legacy/index.js';
|
|
22
|
-
export { HTTP_ROUTE_PUBLICATION } from './legacy/index.js';
|
package/dist/routes/index.js
CHANGED
|
@@ -14,6 +14,3 @@ export { decodeRouting, decodeMiss, decodeStale, HTTP_ROUTE_DIGEST, HTTP_ROUTE_I
|
|
|
14
14
|
export { select } from './select.js';
|
|
15
15
|
export { decodeStreamFrame, encodeStreamFrame, STREAM_MEDIA_TYPE, } from './stream.js';
|
|
16
16
|
export { templatesOverlap } from './template.js';
|
|
17
|
-
/** @deprecated Native routes of a v3-input destination; use the release-bound Table and decoders. */
|
|
18
|
-
export * as legacy from './legacy/index.js';
|
|
19
|
-
export { HTTP_ROUTE_PUBLICATION } from './legacy/index.js';
|
package/dist/routes/request.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Value } from '@astrale-os/kernel-dsl/value';
|
|
2
|
-
import type { Call,
|
|
2
|
+
import type { Call, Via } from '../invocation/index.js';
|
|
3
3
|
import type { HttpMethod } from '../release/route.js';
|
|
4
4
|
/** Canonical invocation values presented to or returned from a native route mapping. */
|
|
5
5
|
export interface Invocation {
|
|
@@ -7,7 +7,7 @@ export interface Invocation {
|
|
|
7
7
|
readonly credential?: string;
|
|
8
8
|
/** The request channel that carried `credential`; `cookie` is ambient (CSRF-exposed). */
|
|
9
9
|
readonly credentialIn?: 'header' | 'cookie' | 'query';
|
|
10
|
-
readonly routing?: Via
|
|
10
|
+
readonly routing?: Via;
|
|
11
11
|
readonly method?: Exclude<HttpMethod, '*'>;
|
|
12
12
|
}
|
|
13
13
|
export interface Request {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { DomainRelease } from '../release/release.js';
|
|
2
2
|
import type { Route } from './table.js';
|
|
3
|
-
/** The
|
|
3
|
+
/** The canonical Release fields read by route reservation admission. */
|
|
4
4
|
export type Placed = Pick<DomainRelease, 'origin' | 'identity' | 'schema' | 'bindings' | 'routes' | 'delivery'>;
|
|
5
|
-
export declare function rejectReserved(
|
|
5
|
+
export declare function rejectReserved(release: Placed, entries: readonly Route[]): void;
|
|
@@ -1,23 +1,22 @@
|
|
|
1
1
|
import * as issuer from '../issuer/index.js';
|
|
2
2
|
import { bundleUrl } from '../release/bundle.js';
|
|
3
|
-
import { PATH as PUBLICATION_PATH } from '../release/legacy/publication.js';
|
|
4
3
|
import { PATH as RELEASE_PATH } from '../release/release.js';
|
|
5
4
|
import { fail } from './error.js';
|
|
6
5
|
import { templateUrl, templatesOverlap } from './template.js';
|
|
7
|
-
const STATIC_RESERVED_PATHS = new Set([RELEASE_PATH
|
|
8
|
-
export function rejectReserved(
|
|
9
|
-
const discovery = issuer.paths(
|
|
6
|
+
const STATIC_RESERVED_PATHS = new Set([RELEASE_PATH]);
|
|
7
|
+
export function rejectReserved(release, entries) {
|
|
8
|
+
const discovery = issuer.paths(release.identity.issuer);
|
|
10
9
|
const reservedPaths = new Set([...STATIC_RESERVED_PATHS, discovery.configuration, discovery.keys]);
|
|
11
10
|
const reservedUrls = [
|
|
12
|
-
|
|
13
|
-
...(
|
|
14
|
-
...
|
|
11
|
+
release.schema.bundle.href,
|
|
12
|
+
...(release.delivery === undefined ? [] : [release.delivery.href]),
|
|
13
|
+
...release.bindings.callables.flatMap(({ endpoint }) => [
|
|
15
14
|
endpoint.http,
|
|
16
15
|
...(endpoint.websocket === undefined ? [] : [httpUrlForWebSocket(endpoint.websocket)]),
|
|
17
16
|
]),
|
|
18
17
|
];
|
|
19
|
-
const addressed = bundleUrl(
|
|
20
|
-
const bundlePattern =
|
|
18
|
+
const addressed = bundleUrl(release.identity.issuer, release.schema.bundle.ref);
|
|
19
|
+
const bundlePattern = release.schema.bundle.href === addressed
|
|
21
20
|
? `${addressed.slice(0, addressed.lastIndexOf('/') + 1)}{artifact}`
|
|
22
21
|
: undefined;
|
|
23
22
|
for (const entry of entries) {
|
package/dist/routes/routing.d.ts
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import type * as invocation from '../invocation/index.js';
|
|
2
2
|
import type { Sha256Digest } from '../release/digest.js';
|
|
3
|
-
import type { PublicationRef } from '../release/legacy/reference.js';
|
|
4
3
|
import type { ReleaseRef } from '../release/reference.js';
|
|
5
4
|
import type { HttpRequest } from './request.js';
|
|
6
5
|
export interface StaleControl {
|
|
7
6
|
readonly kind: 'stale';
|
|
8
|
-
/** Current
|
|
7
|
+
/** Current release digest. */
|
|
9
8
|
readonly current: Sha256Digest;
|
|
10
9
|
}
|
|
11
10
|
export interface MissControl {
|
|
@@ -14,13 +13,6 @@ export interface MissControl {
|
|
|
14
13
|
/** The references one release-backed destination answers native routes for. */
|
|
15
14
|
export interface ServedReferences {
|
|
16
15
|
readonly release: ReleaseRef;
|
|
17
|
-
/**
|
|
18
|
-
* Reference of the frozen v3 projection the destination serves at `domain.json`, which a
|
|
19
|
-
* legacy native-route If-Match names by its Publication ETag.
|
|
20
|
-
*
|
|
21
|
-
* @deprecated Successor: the release digest in If-Match, emitted by the breaking release (AM-1).
|
|
22
|
-
*/
|
|
23
|
-
readonly projection: PublicationRef;
|
|
24
16
|
}
|
|
25
17
|
/** If-Match carries the routed digest of a native route request (`invocation.routedDigest`). */
|
|
26
18
|
export declare const HTTP_ROUTE_DIGEST: 'if-match';
|
|
@@ -30,14 +22,10 @@ export declare const HTTP_ROUTE_STALE_STATUS: 412;
|
|
|
30
22
|
export declare const HTTP_ROUTE_MISS: 'x-astrale-route-miss';
|
|
31
23
|
export declare const HTTP_ROUTE_MISS_STATUS: 421;
|
|
32
24
|
/**
|
|
33
|
-
* Decode
|
|
34
|
-
*
|
|
35
|
-
* ETag a legacy `PublicationVia`. An If-Match naming any other strong digest is stale whether or
|
|
36
|
-
* not the issuer header is present, as a Server answers before decoding; otherwise both headers
|
|
37
|
-
* are required. Stale reports the projection ETag as current, the legacy meaning every
|
|
38
|
-
* native-route value keeps until the breaking release (AM-1).
|
|
25
|
+
* Decode a native route witness against the served release. A different strong digest is stale
|
|
26
|
+
* before issuer admission; otherwise the digest and issuer must occur together.
|
|
39
27
|
*/
|
|
40
|
-
export declare function decodeRouting(input: Pick<HttpRequest, 'headers'>, served: ServedReferences): invocation.Via |
|
|
28
|
+
export declare function decodeRouting(input: Pick<HttpRequest, 'headers'>, served: ServedReferences): invocation.Via | StaleControl | undefined;
|
|
41
29
|
/** Emit the reserved stale header naming `current` (see `StaleControl.current`). */
|
|
42
30
|
export declare function staleHeaders(current: Sha256Digest): Readonly<Record<string, string>>;
|
|
43
31
|
export declare function decodeStale(status: number, headers: HttpRequest['headers']): StaleControl | undefined;
|
package/dist/routes/routing.js
CHANGED
|
@@ -8,12 +8,8 @@ export const HTTP_ROUTE_STALE_STATUS = 412;
|
|
|
8
8
|
export const HTTP_ROUTE_MISS = 'x-astrale-route-miss';
|
|
9
9
|
export const HTTP_ROUTE_MISS_STATUS = 421;
|
|
10
10
|
/**
|
|
11
|
-
* Decode
|
|
12
|
-
*
|
|
13
|
-
* ETag a legacy `PublicationVia`. An If-Match naming any other strong digest is stale whether or
|
|
14
|
-
* not the issuer header is present, as a Server answers before decoding; otherwise both headers
|
|
15
|
-
* are required. Stale reports the projection ETag as current, the legacy meaning every
|
|
16
|
-
* native-route value keeps until the breaking release (AM-1).
|
|
11
|
+
* Decode a native route witness against the served release. A different strong digest is stale
|
|
12
|
+
* before issuer admission; otherwise the digest and issuer must occur together.
|
|
17
13
|
*/
|
|
18
14
|
export function decodeRouting(input, served) {
|
|
19
15
|
const encodedDigest = reservedHeader(input.headers, HTTP_ROUTE_DIGEST);
|
|
@@ -21,8 +17,8 @@ export function decodeRouting(input, served) {
|
|
|
21
17
|
if (encodedDigest === undefined && encodedIssuer === undefined)
|
|
22
18
|
return undefined;
|
|
23
19
|
const named = encodedDigest === undefined ? undefined : strongDigest(encodedDigest);
|
|
24
|
-
if (named !== undefined && named !== served.release.digest
|
|
25
|
-
return Object.freeze({ kind: 'stale', current: served.
|
|
20
|
+
if (named !== undefined && named !== served.release.digest) {
|
|
21
|
+
return Object.freeze({ kind: 'stale', current: served.release.digest });
|
|
26
22
|
}
|
|
27
23
|
if (encodedDigest === undefined || encodedIssuer === undefined) {
|
|
28
24
|
fail('NATIVE_ROUTE_ROUTING_INVALID', `${HTTP_ROUTE_DIGEST} and ${HTTP_ROUTE_ISSUER} must occur together.`);
|
|
@@ -31,9 +27,7 @@ export function decodeRouting(input, served) {
|
|
|
31
27
|
fail('NATIVE_ROUTE_ROUTING_INVALID', 'If-Match must contain exactly one strong quoted digest.');
|
|
32
28
|
}
|
|
33
29
|
const issuer = acceptIssuerHeader(encodedIssuer, HTTP_ROUTE_ISSUER);
|
|
34
|
-
return
|
|
35
|
-
? Object.freeze({ kind: 'via', release: served.release, issuer })
|
|
36
|
-
: Object.freeze({ kind: 'via', publication: served.projection, issuer });
|
|
30
|
+
return Object.freeze({ kind: 'via', release: served.release, issuer });
|
|
37
31
|
}
|
|
38
32
|
/** Emit the reserved stale header naming `current` (see `StaleControl.current`). */
|
|
39
33
|
export function staleHeaders(current) {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
export declare const PLACEHOLDER: RegExp;
|
|
2
2
|
export declare function validateTemplate(href: string): void;
|
|
3
3
|
export declare function templateUrl(href: string): URL;
|
|
4
|
-
export declare function routePattern(href: string): string;
|
|
5
4
|
export declare function templatesOverlap(left: string, right: string): boolean;
|
|
6
5
|
export declare function matchTemplate(template: string, input: string): Record<string, string> | undefined;
|
|
7
6
|
export declare function encodeTemplate(value: unknown, catchall: string | undefined, host: boolean): string;
|
package/dist/routes/template.js
CHANGED
|
@@ -43,9 +43,6 @@ export function templateUrl(href) {
|
|
|
43
43
|
throw cause;
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
|
-
export function routePattern(href) {
|
|
47
|
-
return href.replaceAll(PLACEHOLDER, (_whole, _name, catchall) => catchall === '+' ? '{+}' : catchall === '*' ? '{*}' : '{}');
|
|
48
|
-
}
|
|
49
46
|
export function templatesOverlap(left, right) {
|
|
50
47
|
const leftUrl = templateUrl(left);
|
|
51
48
|
const rightUrl = templateUrl(right);
|
|
@@ -31,15 +31,14 @@ export interface Module {
|
|
|
31
31
|
/** Immutable portable closure selected by one local Schema installation source. */
|
|
32
32
|
export interface RuntimeArtifact {
|
|
33
33
|
readonly format: 'astrale.domain-runtime-artifact';
|
|
34
|
-
readonly version:
|
|
34
|
+
readonly version: 3;
|
|
35
35
|
readonly issuer: IssuerId;
|
|
36
36
|
readonly bundle: Ref;
|
|
37
37
|
readonly requirements: Requirements;
|
|
38
38
|
readonly modules: readonly [Module, ...Module[]];
|
|
39
39
|
}
|
|
40
40
|
export declare const MEDIA_TYPE: 'application/vnd.astrale.domain-runtime+json;v=3';
|
|
41
|
-
export declare
|
|
42
|
-
export declare function mediaType(input: Pick<RuntimeArtifact, 'version'>): typeof MEDIA_TYPE | typeof LEGACY_MEDIA_TYPE;
|
|
41
|
+
export declare function mediaType(_input: Pick<RuntimeArtifact, 'version'>): typeof MEDIA_TYPE;
|
|
43
42
|
export declare function accept(input: unknown): RuntimeArtifact;
|
|
44
43
|
export declare function encode(input: RuntimeArtifact): Uint8Array;
|
|
45
44
|
export declare function runtimeDigest(input: RuntimeArtifact): Digest;
|
package/dist/runtime/artifact.js
CHANGED
|
@@ -3,27 +3,22 @@ import { patterns } from '@astrale-os/kernel-dsl/v1/addressing';
|
|
|
3
3
|
import * as portable from '@astrale-os/kernel-dsl/value';
|
|
4
4
|
import { sha256 } from '@noble/hashes/sha2.js';
|
|
5
5
|
import * as artifact from '../artifact/index.js';
|
|
6
|
-
import {
|
|
7
|
-
import { admitRequirements } from '../release/legacy/requirements.js';
|
|
6
|
+
import { admitRequirements } from '../release/requirements.js';
|
|
8
7
|
export const MEDIA_TYPE = 'application/vnd.astrale.domain-runtime+json;v=3';
|
|
9
|
-
export
|
|
10
|
-
|
|
11
|
-
return input.version === 2 ? LEGACY_MEDIA_TYPE : MEDIA_TYPE;
|
|
8
|
+
export function mediaType(_input) {
|
|
9
|
+
return MEDIA_TYPE;
|
|
12
10
|
}
|
|
13
11
|
export function accept(input) {
|
|
14
12
|
const root = record(input, 'Domain Runtime artifact');
|
|
15
13
|
exact(root, ['bundle', 'format', 'issuer', 'modules', 'requirements', 'version']);
|
|
16
|
-
if (root.format !== 'astrale.domain-runtime-artifact' ||
|
|
17
|
-
(root.version !== 2 && root.version !== 3)) {
|
|
14
|
+
if (root.format !== 'astrale.domain-runtime-artifact' || root.version !== 3) {
|
|
18
15
|
invalid('Domain Runtime artifact format or version is unsupported.');
|
|
19
16
|
}
|
|
20
17
|
if (typeof root.issuer !== 'string')
|
|
21
18
|
invalid('Domain Runtime artifact issuer is invalid.');
|
|
22
19
|
const admittedIssuer = acceptIssuer(root.issuer);
|
|
23
20
|
const bundle = artifact.accept(root.bundle);
|
|
24
|
-
const requirements = root.
|
|
25
|
-
? decodeLegacyRequirements(root.requirements)
|
|
26
|
-
: admitRequirements(root.requirements);
|
|
21
|
+
const requirements = admitRequirements(root.requirements);
|
|
27
22
|
if (!Array.isArray(root.modules) || root.modules.length === 0) {
|
|
28
23
|
invalid('Domain Runtime artifact requires at least one Module.');
|
|
29
24
|
}
|
|
@@ -42,15 +37,10 @@ export function accept(input) {
|
|
|
42
37
|
});
|
|
43
38
|
}
|
|
44
39
|
export function encode(input) {
|
|
45
|
-
return portable.json.encode(
|
|
40
|
+
return portable.json.encode(accept(input));
|
|
46
41
|
}
|
|
47
42
|
export function runtimeDigest(input) {
|
|
48
|
-
return digestBytes(portable.json.encode(
|
|
49
|
-
}
|
|
50
|
-
function wire(input) {
|
|
51
|
-
return input.version === 2
|
|
52
|
-
? { ...input, requirements: encodeLegacyRequirements(input.requirements) }
|
|
53
|
-
: input;
|
|
43
|
+
return digestBytes(portable.json.encode(input));
|
|
54
44
|
}
|
|
55
45
|
export function acceptExecutable(input) {
|
|
56
46
|
return executable(input, 0);
|
package/dist/runtime/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { MEDIA_TYPE,
|
|
1
|
+
export { MEDIA_TYPE, mediaType, accept, acceptExecutable, encode, executableClosure, executableDigest, runtimeDigest, type Digest, type Executable, type ExecutableDependency, type Export, type Module, type RuntimeArtifact, type Ref, } from './artifact.js';
|
package/dist/runtime/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { MEDIA_TYPE,
|
|
1
|
+
export { MEDIA_TYPE, mediaType, accept, acceptExecutable, encode, executableClosure, executableDigest, runtimeDigest, } from './artifact.js';
|
|
@@ -1,9 +1,4 @@
|
|
|
1
1
|
import type { InstallResult } from './result.js';
|
|
2
|
-
export declare const MEDIA_TYPE: 'application/vnd.astrale.schema-installation.
|
|
2
|
+
export declare const MEDIA_TYPE: 'application/vnd.astrale.schema-installation.v3+json';
|
|
3
3
|
export declare function encode(result: InstallResult): Promise<Uint8Array>;
|
|
4
4
|
export declare function decode(bytes: Uint8Array, maximumBytes: number): Promise<InstallResult>;
|
|
5
|
-
/**
|
|
6
|
-
* Package-private: admit one decoded installation result. Shared with the pre-R1 representation in
|
|
7
|
-
* `./legacy/`, which decodes other bytes into this same wire value.
|
|
8
|
-
*/
|
|
9
|
-
export declare function accept(input: unknown): InstallResult;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { installReceipt } from '@astrale-os/kernel-core/schema/kernel/syscalls/contracts';
|
|
2
2
|
import { json } from '@astrale-os/kernel-dsl/value';
|
|
3
3
|
import { acceptDomainInfo } from './introspection/index.js';
|
|
4
|
-
export const MEDIA_TYPE = 'application/vnd.astrale.schema-installation.
|
|
4
|
+
export const MEDIA_TYPE = 'application/vnd.astrale.schema-installation.v3+json';
|
|
5
5
|
const encoder = new TextEncoder();
|
|
6
6
|
export async function encode(result) {
|
|
7
7
|
return encoder.encode(json.serialize(accept(result)));
|
|
@@ -22,11 +22,7 @@ export async function decode(bytes, maximumBytes) {
|
|
|
22
22
|
}
|
|
23
23
|
return accept(value);
|
|
24
24
|
}
|
|
25
|
-
|
|
26
|
-
* Package-private: admit one decoded installation result. Shared with the pre-R1 representation in
|
|
27
|
-
* `./legacy/`, which decodes other bytes into this same wire value.
|
|
28
|
-
*/
|
|
29
|
-
export function accept(input) {
|
|
25
|
+
function accept(input) {
|
|
30
26
|
const value = record(input);
|
|
31
27
|
if (value.changed === true) {
|
|
32
28
|
exact(value, ['changed', 'receipt']);
|
|
@@ -1,17 +1,8 @@
|
|
|
1
1
|
import type { introspection } from '@astrale-os/kernel-core/schema';
|
|
2
|
-
import type {
|
|
3
|
-
export declare const MEDIA_TYPE: 'application/vnd.astrale.schema-introspection.
|
|
2
|
+
import type { DomainDependencies, DomainInfo, Limits, ResultFor } from './result.js';
|
|
3
|
+
export declare const MEDIA_TYPE: 'application/vnd.astrale.schema-introspection.v4+json';
|
|
4
4
|
export declare function encode<Input extends introspection.Introspection>(input: Input, result: ResultFor<Input>): Promise<Uint8Array>;
|
|
5
5
|
export declare function decode<Input extends introspection.Introspection>(input: Input, bytes: Uint8Array, limits: Limits): Promise<ResultFor<Input>>;
|
|
6
|
-
/**
|
|
7
|
-
* Package-private: admit one decoded evidence value for an admitted request. Shared with the
|
|
8
|
-
* pre-R1 representation in `../legacy/`, which decodes other bytes into this same wire value.
|
|
9
|
-
*/
|
|
10
|
-
export declare function acceptEvidence(request: introspection.Introspection, decoded: unknown, limits: Limits): DomainInfo | DomainBundle | DomainDependencies | readonly InstalledRelease[];
|
|
11
|
-
/** Package-private: admit the evidence bounds a request declares. Shared with `../legacy/`. */
|
|
12
|
-
export declare function admitLimits(request: introspection.Introspection, limits: Limits): void;
|
|
13
6
|
/** Admit dependency bindings: origin-ordered, one per origin, each label agreeing with its revisions. */
|
|
14
7
|
export declare function acceptDomainDependencies(input: unknown): DomainDependencies;
|
|
15
8
|
export declare function acceptDomainInfo(input: unknown): DomainInfo;
|
|
16
|
-
/** Package-private: admit one introspection request. Shared with `../legacy/`. */
|
|
17
|
-
export declare function admitRequest(input: introspection.Introspection): introspection.Introspection;
|
|
@@ -4,9 +4,8 @@ import * as bundle from '@astrale-os/kernel-dsl/v1/bundle/transport';
|
|
|
4
4
|
import { revision as schemaRevision } from '@astrale-os/kernel-dsl/v1/schema/revision';
|
|
5
5
|
import { json } from '@astrale-os/kernel-dsl/value';
|
|
6
6
|
import { admitCallableBinding, admitViewBinding } from '../../../release/bindings/index.js';
|
|
7
|
-
import
|
|
8
|
-
|
|
9
|
-
export const MEDIA_TYPE = 'application/vnd.astrale.schema-introspection.v3+json';
|
|
7
|
+
import * as release from '../../../release/index.js';
|
|
8
|
+
export const MEDIA_TYPE = 'application/vnd.astrale.schema-introspection.v4+json';
|
|
10
9
|
const encoder = new TextEncoder();
|
|
11
10
|
const serializedBundles = new WeakMap();
|
|
12
11
|
const admittedBundles = new Map();
|
|
@@ -37,7 +36,7 @@ export async function decode(input, bytes, limits) {
|
|
|
37
36
|
if (!(bytes instanceof Uint8Array))
|
|
38
37
|
invalid('Schema introspection evidence must be binary.');
|
|
39
38
|
admitLimits(request, limits);
|
|
40
|
-
const maximumEvidenceBytes = limits.
|
|
39
|
+
const maximumEvidenceBytes = limits.maximumReleaseBytes +
|
|
41
40
|
(request.kind === 'bundle' ? BUNDLE_ESCAPE_FACTOR * limits.maximumBundleBytes : 0) +
|
|
42
41
|
4_096;
|
|
43
42
|
if (bytes.byteLength > maximumEvidenceBytes) {
|
|
@@ -57,11 +56,7 @@ export async function decode(input, bytes, limits) {
|
|
|
57
56
|
}
|
|
58
57
|
return acceptEvidence(request, decoded, limits);
|
|
59
58
|
}
|
|
60
|
-
|
|
61
|
-
* Package-private: admit one decoded evidence value for an admitted request. Shared with the
|
|
62
|
-
* pre-R1 representation in `../legacy/`, which decodes other bytes into this same wire value.
|
|
63
|
-
*/
|
|
64
|
-
export function acceptEvidence(request, decoded, limits) {
|
|
59
|
+
function acceptEvidence(request, decoded, limits) {
|
|
65
60
|
if (request.kind === 'installed')
|
|
66
61
|
return acceptInstalledReleases(decoded);
|
|
67
62
|
const result = request.kind === 'bundle'
|
|
@@ -72,9 +67,9 @@ export function acceptEvidence(request, decoded, limits) {
|
|
|
72
67
|
proveRequestedOrigin(request, result);
|
|
73
68
|
return result;
|
|
74
69
|
}
|
|
75
|
-
/**
|
|
76
|
-
|
|
77
|
-
admitLimit(limits.
|
|
70
|
+
/** Admit the evidence bounds a request declares. */
|
|
71
|
+
function admitLimits(request, limits) {
|
|
72
|
+
admitLimit(limits.maximumReleaseBytes, 'Release');
|
|
78
73
|
if (request.kind === 'bundle')
|
|
79
74
|
admitLimit(limits.maximumBundleBytes, 'Bundle');
|
|
80
75
|
}
|
|
@@ -174,19 +169,6 @@ function installedPin(input) {
|
|
|
174
169
|
build: digest(value.build, 'Installed build'),
|
|
175
170
|
});
|
|
176
171
|
}
|
|
177
|
-
// Deprecated legacy v2/v3 pin: deleted with the `legacy` variant of `InstalledPin`, in the
|
|
178
|
-
// breaking release that deletes `runtime/schema/installation/source/legacy/`.
|
|
179
|
-
if (value.kind === 'legacy') {
|
|
180
|
-
exact(value, ['document', 'etag', 'kind'], 'Installed legacy pin');
|
|
181
|
-
if (value.document !== 2 && value.document !== 3) {
|
|
182
|
-
invalid('Installed legacy pin document version is invalid.');
|
|
183
|
-
}
|
|
184
|
-
return Object.freeze({
|
|
185
|
-
kind: 'legacy',
|
|
186
|
-
document: value.document,
|
|
187
|
-
etag: digest(value.etag, 'Installed legacy Publication'),
|
|
188
|
-
});
|
|
189
|
-
}
|
|
190
172
|
return invalid('Installed pin kind is invalid.');
|
|
191
173
|
}
|
|
192
174
|
function inFlightIssuers(input, current) {
|
|
@@ -279,7 +261,7 @@ function encodeDomainInfo(input) {
|
|
|
279
261
|
}
|
|
280
262
|
export function acceptDomainInfo(input) {
|
|
281
263
|
const value = record(input, 'Domain info');
|
|
282
|
-
exact(value, ['bindings', 'capabilities', 'generation', 'origin', '
|
|
264
|
+
exact(value, ['bindings', 'capabilities', 'generation', 'origin', 'release', 'readiness', 'revision'], 'Domain info');
|
|
283
265
|
if (typeof value.origin !== 'string' || !patterns.origin.test(value.origin)) {
|
|
284
266
|
invalid('Domain info origin is invalid.');
|
|
285
267
|
}
|
|
@@ -288,29 +270,29 @@ export function acceptDomainInfo(input) {
|
|
|
288
270
|
}
|
|
289
271
|
const origin = value.origin;
|
|
290
272
|
const revision = value.revision;
|
|
291
|
-
const published =
|
|
273
|
+
const published = releaseReference(value.release, origin, revision);
|
|
292
274
|
return Object.freeze({
|
|
293
275
|
origin,
|
|
294
276
|
revision,
|
|
295
277
|
generation: digest(value.generation, 'Domain generation'),
|
|
296
|
-
|
|
278
|
+
release: published,
|
|
297
279
|
readiness: digest(value.readiness, 'Domain readiness'),
|
|
298
280
|
capabilities: capabilities(value.capabilities),
|
|
299
281
|
bindings: bindings(value.bindings, origin),
|
|
300
282
|
});
|
|
301
283
|
}
|
|
302
|
-
function
|
|
284
|
+
function releaseReference(input, origin, revision) {
|
|
303
285
|
if (input === null)
|
|
304
286
|
return null;
|
|
305
287
|
let admitted;
|
|
306
288
|
try {
|
|
307
|
-
admitted =
|
|
289
|
+
admitted = release.acceptReference(input);
|
|
308
290
|
}
|
|
309
291
|
catch (cause) {
|
|
310
|
-
throw new TypeError('Domain
|
|
292
|
+
throw new TypeError('Domain Release metadata is invalid.', { cause });
|
|
311
293
|
}
|
|
312
294
|
if (admitted.origin !== origin || admitted.revision !== revision) {
|
|
313
|
-
invalid('Domain
|
|
295
|
+
invalid('Domain Release metadata does not match its Schema coordinate.');
|
|
314
296
|
}
|
|
315
297
|
return admitted;
|
|
316
298
|
}
|
|
@@ -322,10 +304,10 @@ function bindings(input, origin) {
|
|
|
322
304
|
invalid('Domain bindings are invalid.');
|
|
323
305
|
}
|
|
324
306
|
try {
|
|
325
|
-
return
|
|
307
|
+
return Object.freeze({
|
|
326
308
|
callables: Object.freeze(callables.map((entry) => admitCallableBinding(entry, origin))),
|
|
327
309
|
views: Object.freeze(views.map((entry) => admitViewBinding(entry, origin))),
|
|
328
|
-
})
|
|
310
|
+
});
|
|
329
311
|
}
|
|
330
312
|
catch (cause) {
|
|
331
313
|
throw new TypeError('Domain bindings are invalid.', { cause });
|
|
@@ -340,8 +322,8 @@ function capabilities(input) {
|
|
|
340
322
|
const value = record(input, 'Domain capabilities');
|
|
341
323
|
exact(value, ['materialized', 'requested'], 'Domain capabilities');
|
|
342
324
|
try {
|
|
343
|
-
const requested =
|
|
344
|
-
const materialized =
|
|
325
|
+
const requested = release.admitRequirements({ capabilities: value.requested }).capabilities;
|
|
326
|
+
const materialized = release.admitRequirements({
|
|
345
327
|
capabilities: value.materialized,
|
|
346
328
|
}).capabilities;
|
|
347
329
|
return Object.freeze({ requested, materialized });
|
|
@@ -350,8 +332,8 @@ function capabilities(input) {
|
|
|
350
332
|
throw new TypeError('Domain capabilities are invalid.', { cause });
|
|
351
333
|
}
|
|
352
334
|
}
|
|
353
|
-
/**
|
|
354
|
-
|
|
335
|
+
/** Admit one introspection request. */
|
|
336
|
+
function admitRequest(input) {
|
|
355
337
|
const value = record(input, 'Schema introspection request');
|
|
356
338
|
if (value.kind === 'installed') {
|
|
357
339
|
exact(value, ['kind'], 'Schema introspection request');
|
|
@@ -1,28 +1,21 @@
|
|
|
1
1
|
import type { IssuerId } from '@astrale-os/kernel-core/auth/issuer';
|
|
2
2
|
import type { introspection } from '@astrale-os/kernel-core/schema';
|
|
3
3
|
import type { bundle, Key, Revision } from '@astrale-os/kernel-dsl/v1';
|
|
4
|
-
import type { BuildDigest, ReleaseDigest } from '../../../release/index.js';
|
|
5
|
-
import type { Publication, PublicationRef, PublicationRequirements } from '../../../release/legacy/index.js';
|
|
4
|
+
import type { BuildDigest, ReleaseDigest, ReleaseRef, DomainRelease, Requirements } from '../../../release/index.js';
|
|
6
5
|
export type Digest = `sha256:${string}`;
|
|
7
6
|
/** Lightweight proof of one exact ready installed Domain generation. */
|
|
8
7
|
export interface DomainInfo {
|
|
9
8
|
readonly origin: Key.Origin;
|
|
10
9
|
readonly revision: Revision;
|
|
11
10
|
readonly generation: Digest;
|
|
12
|
-
/**
|
|
13
|
-
|
|
14
|
-
* the frozen v3 projection for a v4 pin.
|
|
15
|
-
*
|
|
16
|
-
* @deprecated Successor: `DomainInfo.release`, the installed `ReleaseRef`, emitted by the
|
|
17
|
-
* breaking release (AM-1).
|
|
18
|
-
*/
|
|
19
|
-
readonly publication: PublicationRef | null;
|
|
11
|
+
/** Exact reference of the ready pinned release, or null for a local Domain. */
|
|
12
|
+
readonly release: ReleaseRef | null;
|
|
20
13
|
readonly readiness: Digest;
|
|
21
14
|
readonly capabilities: {
|
|
22
|
-
readonly requested:
|
|
23
|
-
readonly materialized:
|
|
15
|
+
readonly requested: Requirements['capabilities'];
|
|
16
|
+
readonly materialized: Requirements['capabilities'];
|
|
24
17
|
};
|
|
25
|
-
readonly bindings:
|
|
18
|
+
readonly bindings: DomainRelease['bindings'];
|
|
26
19
|
}
|
|
27
20
|
/** Explicit complete Bundle observed coherently with its ready Domain generation. */
|
|
28
21
|
export interface DomainBundle {
|
|
@@ -45,31 +38,12 @@ export interface DomainDependencies {
|
|
|
45
38
|
readonly domain: DomainInfo;
|
|
46
39
|
readonly dependencies: readonly DependencyBinding[];
|
|
47
40
|
}
|
|
48
|
-
/**
|
|
49
|
-
|
|
50
|
-
* beside the build digest it runs, or a legacy v2/v3 Publication by its strong ETag.
|
|
51
|
-
*/
|
|
52
|
-
export type InstalledPin = ReleasePin | LegacyPin;
|
|
53
|
-
/** A `DomainRelease` v4 pin: its release digest beside the build digest it runs. */
|
|
54
|
-
interface ReleasePin {
|
|
41
|
+
/** A DomainRelease v4 pin: its release digest beside the build digest it runs. */
|
|
42
|
+
export interface InstalledPin {
|
|
55
43
|
readonly kind: 'release';
|
|
56
44
|
readonly release: ReleaseDigest;
|
|
57
45
|
readonly build: BuildDigest;
|
|
58
46
|
}
|
|
59
|
-
/**
|
|
60
|
-
* A legacy v2/v3 Publication pin: its document version and strong ETag.
|
|
61
|
-
*
|
|
62
|
-
* @deprecated Successor: the `release` pin. Short-term consumer: the installations that still pin
|
|
63
|
-
* a v2/v3 Publication, such as the astrale Host's v3 installs until Shell is republished as a
|
|
64
|
-
* release. Deleted, with its codec branch, in the separate breaking release that deletes
|
|
65
|
-
* `runtime/schema/installation/source/legacy/`, once no installation pins a v2/v3 Publication
|
|
66
|
-
* (the conditions of `protocol/release/legacy/index.ts`).
|
|
67
|
-
*/
|
|
68
|
-
interface LegacyPin {
|
|
69
|
-
readonly kind: 'legacy';
|
|
70
|
-
readonly document: 2 | 3;
|
|
71
|
-
readonly etag: Digest;
|
|
72
|
-
}
|
|
73
47
|
/**
|
|
74
48
|
* The issuer of a release one installation replaced, as the Kernel records it: accepted while its
|
|
75
49
|
* work drains, and listed until a later consented install re-pins or prunes it, drained or not.
|
|
@@ -101,7 +75,6 @@ export type ResultFor<Input extends introspection.Introspection> = Input extends
|
|
|
101
75
|
readonly kind: 'dependencies';
|
|
102
76
|
} ? DomainDependencies : DomainInfo;
|
|
103
77
|
export interface Limits {
|
|
104
|
-
readonly
|
|
78
|
+
readonly maximumReleaseBytes: number;
|
|
105
79
|
readonly maximumBundleBytes: number;
|
|
106
80
|
}
|
|
107
|
-
export {};
|