Fix supervised credentials and declare typed RPC records for canvas placement

This commit is contained in:
Timothy J. Aveni
2026-09-13 16:30:17 -07:00
parent 483bc68a94
commit 42af87f8bd
13 changed files with 1618 additions and 1450 deletions
+15 -3
View File
@@ -144,6 +144,8 @@ const typeLabel = (type: ValueType): string => {
return type.name;
case "message":
return `message:${type.descriptorId}`;
case "record":
return `record{${Object.keys(type.fields).sort().map((key) => `${key}:${typeLabel(type.fields[key])}`).join(";")}}`;
case "object-ref":
return type.expectation.kind === "atom"
? `object:atom:${type.expectation.atomId}`
@@ -165,6 +167,10 @@ export const valueTypesEqual = (left: ValueType, right: ValueType): boolean => {
return left.name === (right as typeof left).name;
case "message":
return left.descriptorId === (right as typeof left).descriptorId;
case "record": {
const other = (right as typeof left).fields;
return Object.keys(left.fields).length === Object.keys(other).length && Object.entries(left.fields).every(([key, value]) => Object.hasOwn(other, key) && valueTypesEqual(value, other[key]));
}
case "object-ref": {
const other = (right as typeof left).expectation;
if (left.expectation.kind !== other.kind) {
@@ -220,6 +226,12 @@ const validateValueType = (
indexes: Pick<ValidationIndexes, "atoms" | "interfaces">,
) => {
switch (type.kind) {
case "record":
for (const [name, field] of Object.entries(type.fields)) {
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(name)) issue(issues, "invalid-value-type", path, "Invalid record field name");
validateValueType(issues, field, `${path}.fields.${name}`, indexes);
}
return;
case "builtin":
case "scalar":
return;
@@ -777,9 +789,9 @@ const validateAttachments = (
);
}
validateValueType(issues, attachment.valueType, `${path}.valueType`, indexes);
const containsReference = (type: ValueType): boolean => type.kind === "object-ref" || ((type.kind === "optional" || type.kind === "list") && containsReference(type.value));
if (containsReference(attachment.valueType) || (attachment.storagePolicy.kind === "crdt-document" && containsReference(attachment.storagePolicy.updateType))) {
issue(issues, "invalid-attachment", `${path}.valueType`, "Managed object references belong in graph relationships, not ordinary state");
const containsRpcType = (type: ValueType): boolean => type.kind === "object-ref" || type.kind === "record" || ((type.kind === "optional" || type.kind === "list") && containsRpcType(type.value));
if (containsRpcType(attachment.valueType) || (attachment.storagePolicy.kind === "crdt-document" && containsRpcType(attachment.storagePolicy.updateType))) {
issue(issues, "invalid-attachment", `${path}.valueType`, "Managed object references belong in graph relationships, not ordinary state; record types are RPC-only");
}
if (attachment.storagePolicy.kind === "crdt-document") {
validateValueType(