@astrale-os/kernel-protocol 0.5.0-beta.31 → 0.5.0-beta.33
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/CHANGELOG.md
CHANGED
|
@@ -24,6 +24,24 @@
|
|
|
24
24
|
* the first supported V2 release is a coordinated `1.0.0`, not a compatible continuation of the
|
|
25
25
|
current `0.x` line; package and wire versions remain independent as specified in
|
|
26
26
|
[the protocol architecture](./.spec/architecture.md)
|
|
27
|
+
## [0.5.0-beta.33](https://github.com/astrale-os/kernel/compare/kernel-protocol-v0.5.0-beta.32...kernel-protocol-v0.5.0-beta.33) (2026-08-31)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
### Dependencies
|
|
31
|
+
|
|
32
|
+
* The following workspace dependencies were updated
|
|
33
|
+
* dependencies
|
|
34
|
+
* @astrale-os/kernel-core bumped to 0.9.0-beta.30
|
|
35
|
+
* @astrale-os/kernel-dsl bumped to 0.2.0-beta.23
|
|
36
|
+
|
|
37
|
+
## [0.5.0-beta.32](https://github.com/astrale-os/kernel/compare/kernel-protocol-v0.5.0-beta.31...kernel-protocol-v0.5.0-beta.32) (2026-08-31)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
### Bug Fixes
|
|
41
|
+
|
|
42
|
+
* **api:** keep profile validation runtime-safe ([#589](https://github.com/astrale-os/kernel/issues/589)) ([fd5c5f6](https://github.com/astrale-os/kernel/commit/fd5c5f6e7e6b2a4b617ccffe9efa605c05ea0c52))
|
|
43
|
+
* **protocol:** keep profile identity reference portable ([#592](https://github.com/astrale-os/kernel/issues/592)) ([c942216](https://github.com/astrale-os/kernel/commit/c942216fa52c0344ef74cf1dea49229e7981d9bf))
|
|
44
|
+
|
|
27
45
|
## [0.5.0-beta.31](https://github.com/astrale-os/kernel/compare/kernel-protocol-v0.5.0-beta.30...kernel-protocol-v0.5.0-beta.31) (2026-08-31)
|
|
28
46
|
|
|
29
47
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { MEDIA_TYPE, PATH, url, seal, accept,
|
|
1
|
+
export { MEDIA_TYPE, PATH, url, seal, accept, encode, type Publication } from './publication.js';
|
|
2
2
|
export { acceptBundle, decodeBundle } from './bundle-admission.js';
|
|
3
3
|
export { BUNDLE_MEDIA_TYPE, describeBundle, type BundleDescriptor } from './bundle.js';
|
|
4
4
|
export { verifyBundleBytes } from './bundle-evidence.js';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { MEDIA_TYPE, PATH, url, seal, accept,
|
|
1
|
+
export { MEDIA_TYPE, PATH, url, seal, accept, encode } from './publication.js';
|
|
2
2
|
export { acceptBundle, decodeBundle } from './bundle-admission.js';
|
|
3
3
|
export { BUNDLE_MEDIA_TYPE, describeBundle } from './bundle.js';
|
|
4
4
|
export { verifyBundleBytes } from './bundle-evidence.js';
|
|
@@ -31,16 +31,6 @@ export interface Publication {
|
|
|
31
31
|
readonly routes: readonly HttpRoute[];
|
|
32
32
|
readonly delivery?: DeliveryEndpoint;
|
|
33
33
|
}
|
|
34
|
-
/** Canonical semantic Publication plus its exact coordinate in durable storage. */
|
|
35
|
-
export interface StoredPublication {
|
|
36
|
-
readonly publication: Publication;
|
|
37
|
-
readonly deployedEtag: Etag;
|
|
38
|
-
}
|
|
39
34
|
export declare function seal(input: Content): Publication;
|
|
40
35
|
export declare function accept(input: unknown): Publication;
|
|
41
|
-
/**
|
|
42
|
-
* Admit a canonical Publication retained before the admin-to-authority vocabulary cutover.
|
|
43
|
-
* Network admission remains strict; this one-way reader exists only for already-trusted storage.
|
|
44
|
-
*/
|
|
45
|
-
export declare function acceptStored(input: unknown): StoredPublication;
|
|
46
36
|
export declare function encode(input: Publication): Uint8Array;
|
|
@@ -44,40 +44,6 @@ export function accept(input) {
|
|
|
44
44
|
}
|
|
45
45
|
return publication;
|
|
46
46
|
}
|
|
47
|
-
/**
|
|
48
|
-
* Admit a canonical Publication retained before the admin-to-authority vocabulary cutover.
|
|
49
|
-
* Network admission remains strict; this one-way reader exists only for already-trusted storage.
|
|
50
|
-
*/
|
|
51
|
-
export function acceptStored(input) {
|
|
52
|
-
try {
|
|
53
|
-
const publication = accept(input);
|
|
54
|
-
return deepFreeze({ publication, deployedEtag: publication.etag });
|
|
55
|
-
}
|
|
56
|
-
catch (currentFailure) {
|
|
57
|
-
const value = record(input, 'PUBLICATION_INVALID', 'Expected a Publication object.');
|
|
58
|
-
const requirements = record(value.requirements, 'PUBLICATION_INVALID', 'Publication requirements are invalid.');
|
|
59
|
-
const capabilities = record(requirements.capabilities, 'PUBLICATION_INVALID', 'Publication capability requirements are invalid.');
|
|
60
|
-
if (capabilities.admin === undefined)
|
|
61
|
-
throw currentFailure;
|
|
62
|
-
if (capabilities.authority !== undefined) {
|
|
63
|
-
fail('PUBLICATION_INVALID', 'Publication cannot mix admin and authority requirements.');
|
|
64
|
-
}
|
|
65
|
-
const { etag, ...content } = value;
|
|
66
|
-
const admittedEtag = admitDigest(etag);
|
|
67
|
-
if (admittedEtag !== computeEtag(content)) {
|
|
68
|
-
fail('PUBLICATION_ETAG_MISMATCH', 'Publication ETag does not match its canonical content.');
|
|
69
|
-
}
|
|
70
|
-
const { admin, ...currentCapabilities } = capabilities;
|
|
71
|
-
const admitted = acceptPublication({
|
|
72
|
-
...value,
|
|
73
|
-
requirements: {
|
|
74
|
-
...requirements,
|
|
75
|
-
capabilities: { ...currentCapabilities, authority: admin },
|
|
76
|
-
},
|
|
77
|
-
}, true);
|
|
78
|
-
return deepFreeze({ publication: seal(withoutEtag(admitted)), deployedEtag: admittedEtag });
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
47
|
export function encode(input) {
|
|
82
48
|
return portable.json.encode(input);
|
|
83
49
|
}
|
|
@@ -1,10 +1,13 @@
|
|
|
1
|
-
import { K } from '@astrale-os/kernel-core/schema';
|
|
2
1
|
import { AuthorityOperationOrder } from '@astrale-os/kernel-core/schema/authority/operation';
|
|
3
|
-
import { schema as schemaApi } from '@astrale-os/kernel-dsl/v1';
|
|
4
2
|
import { acceptDefinitionRef, callableAddress, Key } from '@astrale-os/kernel-dsl/v1/addressing';
|
|
5
3
|
import { revision } from '@astrale-os/kernel-dsl/v1/schema/revision';
|
|
6
4
|
import { array, deepFreeze, exact, record, unique } from './content.js';
|
|
7
5
|
import { fail } from './error.js';
|
|
6
|
+
const KernelIdentityClass = Object.freeze({
|
|
7
|
+
origin: 'kernel.astrale.ai',
|
|
8
|
+
kind: 'class',
|
|
9
|
+
name: 'Identity',
|
|
10
|
+
});
|
|
8
11
|
export const ClassOperationOrder = Object.freeze([
|
|
9
12
|
'create',
|
|
10
13
|
'read',
|
|
@@ -106,18 +109,11 @@ export function validateRequirements(root, closure, requirements) {
|
|
|
106
109
|
fail('PUBLICATION_INVALID', 'Class capability requirement names an unknown dependency Class.');
|
|
107
110
|
}
|
|
108
111
|
}
|
|
109
|
-
const resolvedRoot = requirements.capabilities.profiles === undefined
|
|
110
|
-
? undefined
|
|
111
|
-
: schemaApi.resolve(schemaApi.accept(root, {
|
|
112
|
-
get(origin, expectedRevision) {
|
|
113
|
-
return closure.find((dependency) => dependency.origin === origin && revision(dependency) === expectedRevision);
|
|
114
|
-
},
|
|
115
|
-
}));
|
|
116
112
|
for (const profile of requirements.capabilities.profiles ?? []) {
|
|
117
|
-
const subject =
|
|
113
|
+
const subject = root.core.nodes[profile.subject.name];
|
|
118
114
|
if (profile.subject.origin !== root.origin ||
|
|
119
115
|
subject === undefined ||
|
|
120
|
-
!subject.class
|
|
116
|
+
!classSatisfies(root, dependencies, subject.class, KernelIdentityClass)) {
|
|
121
117
|
fail('PUBLICATION_INVALID', 'Capability profile subject must name one local Core Identity.');
|
|
122
118
|
}
|
|
123
119
|
for (const callable of profile.functions ?? []) {
|
|
@@ -137,6 +133,22 @@ export function validateRequirements(root, closure, requirements) {
|
|
|
137
133
|
}
|
|
138
134
|
}
|
|
139
135
|
}
|
|
136
|
+
function classSatisfies(root, dependencies, candidate, expected) {
|
|
137
|
+
const expectedKey = Key.of(expected);
|
|
138
|
+
const visited = new Set();
|
|
139
|
+
const visit = (reference) => {
|
|
140
|
+
const key = Key.of(reference);
|
|
141
|
+
if (key === expectedKey)
|
|
142
|
+
return true;
|
|
143
|
+
if (visited.has(key))
|
|
144
|
+
return false;
|
|
145
|
+
visited.add(key);
|
|
146
|
+
const owner = reference.origin === root.origin ? root : dependencies.get(reference.origin);
|
|
147
|
+
const definition = owner?.classes[reference.name];
|
|
148
|
+
return definition?.kind === 'node' && definition.extends.some(visit);
|
|
149
|
+
};
|
|
150
|
+
return visit(candidate);
|
|
151
|
+
}
|
|
140
152
|
function exactDependencyClosure(root, closure) {
|
|
141
153
|
const supplied = new Map(closure.map((dependency) => [dependency.origin, dependency]));
|
|
142
154
|
const reachable = new Map();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@astrale-os/kernel-protocol",
|
|
3
|
-
"version": "0.5.0-beta.
|
|
3
|
+
"version": "0.5.0-beta.33",
|
|
4
4
|
"description": "Portable Astrale invocation, publication, installation, routing, and issuer protocols",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -133,8 +133,8 @@
|
|
|
133
133
|
"access": "public"
|
|
134
134
|
},
|
|
135
135
|
"dependencies": {
|
|
136
|
-
"@astrale-os/kernel-core": "0.9.0-beta.
|
|
137
|
-
"@astrale-os/kernel-dsl": "0.2.0-beta.
|
|
136
|
+
"@astrale-os/kernel-core": "0.9.0-beta.30",
|
|
137
|
+
"@astrale-os/kernel-dsl": "0.2.0-beta.23",
|
|
138
138
|
"@noble/hashes": "2.3.0"
|
|
139
139
|
},
|
|
140
140
|
"devDependencies": {
|