@tiinex/core 0.19.0 → 0.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. package/package.json +7 -6
  2. package/src/schemas/creation.contracts.js +1 -1
  3. package/src/schemas/party/role/tiinex.party.role.v1.schema.js +5 -0
  4. package/src/schemas/party/role/tiinex.party.role.v1.schema.json +2 -2
  5. package/src/schemas/party/role/tiinex.party.role.v1.schema.md +313 -0
  6. package/src/schemas/party/role/tiinex.party.role.v1.schema.runtime.json +18 -6
  7. package/src/schemas/party/role/tiinex.party.role.v1.validate.js +36 -0
  8. package/src/schemas/schema.reference.js +29 -0
  9. package/src/tooling/portable/adapters/cli/cli.common-author.js +117 -6
  10. package/src/tooling/portable/adapters/cli/cli.common-output.js +19 -0
  11. package/src/tooling/portable/adapters/node/handoff.manufacture.js +26 -4
  12. package/src/tooling/portable/adapters/node/handoff.manufacture.packageParent.js +123 -0
  13. package/src/tooling/portable/audit/audit.capability.js +10 -4
  14. package/src/tooling/portable/grounding/grounding.capsule.js +26 -2
  15. package/src/tooling/portable/grounding/grounding.delegationArtifactAuthority.js +314 -0
  16. package/src/tooling/portable/grounding/grounding.delegationReadiness.js +241 -0
  17. package/src/tooling/portable/grounding/grounding.holderAssignmentModes.js +125 -0
  18. package/src/tooling/portable/grounding/grounding.holderBindingAuthorization.js +49 -50
  19. package/src/tooling/portable/grounding/grounding.readiness.js +19 -3
  20. package/src/tooling/portable/grounding/grounding.readiness.support.js +1 -1
  21. package/src/tooling/portable/handoff/carrierProjection.routeQualification.js +20 -4
  22. package/src/tooling/portable/handoff/coldStartQualification.grounding.js +67 -4
  23. package/src/tooling/portable/handoff/coldStartQualification.materials.js +84 -10
  24. package/src/tooling/portable/handoff/recipientV2.endpointRolePointers.js +1 -1
  25. package/src/tooling/portable/handoff/recipientV2.inspect.projection.js +5 -2
  26. package/src/tooling/portable/handoff/recipientV2.packageV1.build.js +2 -2
  27. package/src/tooling/portable/handoff/recipientV2.topology.js +5 -3
  28. package/src/tooling/portable/handoff/recipientV2.topology.materials.js +0 -0
@@ -0,0 +1,125 @@
1
+ import { deepFreeze, normalizeToken } from '../handoff/coldStartQualification.shared.js';
2
+
3
+ export const HOLDER_ASSIGNMENT_MODE = deepFreeze({
4
+ EXPLICIT_SESSION: 'explicit-session',
5
+ EXPLICIT_USER_SESSION: 'explicit-user-session',
6
+ EXPLICIT_ROLE_INVOCATION: 'explicit-role-invocation',
7
+ HANDOFF: 'handoff',
8
+ EXPLICIT_PARTICIPATION: 'explicit-participation'
9
+ });
10
+
11
+ const KNOWN_MODES = new Set(Object.values(HOLDER_ASSIGNMENT_MODE));
12
+
13
+ export function projectHolderAssignmentModeAuthority(role = {}) {
14
+ const endpointKind = normalizeToken(role?.endpoint?.kind || '');
15
+ if (endpointKind !== 'role') return deepFreeze({
16
+ state: 'not-applicable',
17
+ modes: deepFreeze([]),
18
+ holderState: '',
19
+ source: 'none',
20
+ reasonCode: 'recipient-not-role',
21
+ unknownModes: deepFreeze([]),
22
+ provenance: baseProvenance(role, { basis: 'recipient-not-role', field: 'Assignment Modes' }),
23
+ boundary: 'Holder assignment-mode authority applies only to a selected Role recipient.'
24
+ });
25
+
26
+ const material = role?.material?.artifact || null;
27
+ const relationship = role?.holderRelationshipLoaded || {};
28
+ const holderState = String(relationship.holderState || '').trim();
29
+ const qualifiedMaterial = String(role?.state || '') === 'qualified'
30
+ && String(role?.material?.state || '') === 'qualified'
31
+ && Boolean(material?.path)
32
+ && /^[0-9a-f]{64}$/i.test(String(material?.sha256 || ''));
33
+ if (!qualifiedMaterial) return unresolved(role, holderState, 'qualified-role-holder-authority-not-established', 'none', {
34
+ basis: 'exact-qualified-role-assignment-mode-authority-not-established', field: 'Assignment Modes'
35
+ });
36
+
37
+ const structured = parseStructuredModes(relationship.assignmentModes);
38
+ if (!structured.present) return unresolved(role, holderState, 'holder-assignment-mode-authority-missing', 'qualified-recipient-role-material', {
39
+ basis: 'canonical-assignment-modes-missing', field: 'Assignment Modes'
40
+ });
41
+ if (structured.unknown.length) return unresolved(role, holderState, 'holder-assignment-mode-authority-unknown-token', 'qualified-recipient-role-structured-modes', {
42
+ basis: 'exact-qualified-role-assignment-modes', field: 'Assignment Modes', exactValue: structured.raw, unknownModes: structured.unknown
43
+ });
44
+ if (!structured.modes.length) return unresolved(role, holderState, 'holder-assignment-mode-authority-empty', 'qualified-recipient-role-structured-modes', {
45
+ basis: 'exact-qualified-role-assignment-modes', field: 'Assignment Modes', exactValue: structured.raw
46
+ });
47
+ return deepFreeze({
48
+ state: 'qualified',
49
+ modes: deepFreeze(structured.modes),
50
+ holderState,
51
+ source: 'qualified-recipient-role-structured-modes',
52
+ reasonCode: 'holder-assignment-mode-authority-qualified',
53
+ unknownModes: deepFreeze([]),
54
+ provenance: baseProvenance(role, {
55
+ basis: 'exact-qualified-role-assignment-modes',
56
+ field: 'Assignment Modes',
57
+ exactValue: structured.raw,
58
+ boundary: 'Positive mode authority comes only from the exact structured Assignment Modes field on the qualified current Role. Holder State is diagnostic-only; historical compatibility material does not authorize current holder binding.'
59
+ }),
60
+ boundary: 'Exact structured canonical assignment modes authorize only their named bounded mechanisms; they do not establish a holder, durable identity, participation, delegation, process, source, or acceptance authority.'
61
+ });
62
+ }
63
+
64
+ export function isCanonicalHolderAssignmentMode(value = '') {
65
+ return KNOWN_MODES.has(String(value || '').trim());
66
+ }
67
+
68
+ function parseStructuredModes(value) {
69
+ if (Array.isArray(value)) {
70
+ const raw = value.map((item) => String(item || '').trim()).filter(Boolean);
71
+ const tokens = raw.map(stripCode).filter(Boolean);
72
+ return classifyStructured(tokens, raw.join(', '), true);
73
+ }
74
+ const raw = String(value || '').trim();
75
+ if (!raw) return { present: false, raw: '', modes: [], unknown: [] };
76
+ const tokens = raw.split(',').map((item) => stripCode(item.trim())).filter(Boolean);
77
+ return classifyStructured(tokens, raw, true);
78
+ }
79
+
80
+ function classifyStructured(tokens, raw, present) {
81
+ const modes = [];
82
+ const unknown = [];
83
+ for (const token of tokens) {
84
+ if (KNOWN_MODES.has(token)) {
85
+ if (!modes.includes(token)) modes.push(token);
86
+ } else if (!unknown.includes(token)) unknown.push(token);
87
+ }
88
+ return { present, raw, modes, unknown };
89
+ }
90
+
91
+ function stripCode(value) {
92
+ const text = String(value || '').trim();
93
+ return /^`[^`]+`$/.test(text) ? text.slice(1, -1).trim() : text;
94
+ }
95
+
96
+ function unresolved(role, holderState, reasonCode, source, details = {}) {
97
+ return deepFreeze({
98
+ state: 'unresolved',
99
+ modes: deepFreeze([]),
100
+ holderState,
101
+ source,
102
+ reasonCode,
103
+ unknownModes: deepFreeze([...(details.unknownModes || [])]),
104
+ provenance: baseProvenance(role, details),
105
+ boundary: 'Positive holder assignment-mode authorization is unresolved. Core does not infer canonical modes from Holder State prose, historical Role compatibility, endpoint labels, package placement, session assertions, filenames, or lexical similarity.'
106
+ });
107
+ }
108
+
109
+ function baseProvenance(role = {}, details = {}) {
110
+ const material = role?.material?.artifact || {};
111
+ return deepFreeze({
112
+ basis: String(details.basis || ''),
113
+ roleArtifactPath: String(material.path || ''),
114
+ roleArtifactSha256: String(material.sha256 || ''),
115
+ roleSchemaId: String(material.schemaId || ''),
116
+ roleLabel: String(material.roleLabel || role?.endpoint?.label || ''),
117
+ section: 'Holder Relationship',
118
+ field: String(details.field || 'Assignment Modes'),
119
+ exactValue: String(details.exactValue || ''),
120
+ exactRoleSourcePath: '',
121
+ exactRoleSha256: '',
122
+ decisionArtifact: null,
123
+ boundary: String(details.boundary || 'Only exact structured Assignment Modes on exact qualified current Role material may establish canonical assignment modes. Holder State and historical compatibility material remain non-authoritative for positive authorization.')
124
+ });
125
+ }
@@ -1,81 +1,80 @@
1
- import { deepFreeze, normalizeComparable, normalizeToken } from '../handoff/coldStartQualification.shared.js';
1
+ import { deepFreeze, normalizeToken } from '../handoff/coldStartQualification.shared.js';
2
+ import {
3
+ HOLDER_ASSIGNMENT_MODE,
4
+ isCanonicalHolderAssignmentMode,
5
+ projectHolderAssignmentModeAuthority
6
+ } from './grounding.holderAssignmentModes.js';
2
7
 
3
- export const EXPLICIT_SESSION_OR_HANDOFF_HOLDER_STATE = 'assignable per explicit session or Handoff';
4
- export const CURRENT_ROLE_EXPLICIT_SESSION_OR_HANDOFF_HOLDER_STATE = 'assignable per explicit session, role invocation, or Handoff; no permanent holder asserted';
5
- export const ANCHOR_EXPLICIT_SESSION_OR_HANDOFF_HOLDER_STATE = 'assignable per explicit session or Handoff; no permanent holder asserted';
6
-
7
- const AUTHORIZED_EXPLICIT_SESSION_OR_HANDOFF_STATES = new Set([
8
- normalizeComparable(EXPLICIT_SESSION_OR_HANDOFF_HOLDER_STATE),
9
- normalizeComparable(CURRENT_ROLE_EXPLICIT_SESSION_OR_HANDOFF_HOLDER_STATE),
10
- normalizeComparable(ANCHOR_EXPLICIT_SESSION_OR_HANDOFF_HOLDER_STATE)
11
- ]);
12
-
13
- export function projectHolderBindingAuthorization(role = {}) {
8
+ export function projectHolderBindingAuthorization(role = {}, options = {}) {
14
9
  const endpointKind = normalizeToken(role?.endpoint?.kind || '');
10
+ const requestedMode = String(options.assertionMode || options.assignmentMode || HOLDER_ASSIGNMENT_MODE.EXPLICIT_SESSION).trim();
15
11
  if (endpointKind !== 'role') return deepFreeze({
16
12
  state: 'not-applicable',
17
13
  assignmentMode: '',
14
+ authorizedModes: deepFreeze([]),
18
15
  holderState: '',
19
16
  source: 'none',
20
17
  reasonCode: 'recipient-not-role',
18
+ modeAuthority: projectHolderAssignmentModeAuthority(role),
21
19
  provenance: {
22
- basis: 'recipient-not-role',
23
- roleArtifactPath: '',
24
- roleArtifactSha256: '',
25
- section: 'Holder Relationship',
26
- field: 'Holder State',
27
- boundary: 'Holder-assignment authorization is only applicable when the selected Handoff recipient is a Role endpoint.'
20
+ basis: 'recipient-not-role', roleArtifactPath: '', roleArtifactSha256: '', section: 'Holder Relationship', field: 'Assignment Modes', exactValue: '', assertionMode: '', boundary: 'Holder-assignment authorization is only applicable when the selected Handoff recipient is a Role endpoint.'
28
21
  },
29
22
  boundary: 'No Role assignment authorization is required for a non-Role recipient.'
30
23
  });
31
24
 
32
- const material = role?.material?.artifact || null;
33
- const relationship = role?.holderRelationshipLoaded || {};
34
- const holderState = String(relationship.holderState || '').trim();
35
- const qualifiedMaterial = String(role?.state || '') === 'qualified'
36
- && String(role?.material?.state || '') === 'qualified'
37
- && Boolean(material?.path)
38
- && Boolean(material?.sha256);
39
- const provenance = {
40
- basis: qualifiedMaterial ? 'exact-qualified-role-holder-relationship' : 'exact-qualified-role-holder-relationship-not-established',
41
- roleArtifactPath: String(material?.path || ''),
42
- roleArtifactSha256: String(material?.sha256 || ''),
43
- roleSchemaId: String(material?.schemaId || ''),
44
- roleLabel: String(material?.roleLabel || role?.endpoint?.label || ''),
45
- section: 'Holder Relationship',
46
- field: 'Holder State',
47
- exactValue: holderState,
48
- boundary: 'Only exact qualified recipient Role material may authorize the bounded session assignment mode. Handoff endpoints, transport identity, explicit session input, filenames, and package placement do not provide this authority.'
49
- };
25
+ const modeAuthority = projectHolderAssignmentModeAuthority(role);
26
+ const holderState = String(modeAuthority.holderState || role?.holderRelationshipLoaded?.holderState || '').trim();
27
+ const provenance = deepFreeze({
28
+ ...(modeAuthority.provenance || {}),
29
+ assertionMode: requestedMode,
30
+ boundary: 'The bounded binding result compares one explicit assertion mechanism to exact qualified canonical assignment-mode authority. Holder State prose remains diagnostic-only.'
31
+ });
50
32
 
51
- if (!qualifiedMaterial) return deepFreeze({
33
+ if (modeAuthority.state !== 'qualified') return deepFreeze({
52
34
  state: 'unresolved',
53
- assignmentMode: '',
35
+ assignmentMode: requestedMode,
36
+ authorizedModes: deepFreeze([]),
54
37
  holderState,
55
- source: 'none',
56
- reasonCode: 'qualified-role-holder-authority-not-established',
38
+ source: modeAuthority.source || 'none',
39
+ reasonCode: modeAuthority.reasonCode || 'holder-assignment-mode-authority-unresolved',
40
+ modeAuthority,
57
41
  provenance,
58
- boundary: 'A matching session Role assertion remains unauthorized until exact qualified Role material establishes the assignment mode.'
42
+ boundary: 'A matching Role assertion remains unauthorized until exact qualified canonical assignment-mode authority is established.'
59
43
  });
60
44
 
61
- const assignmentAuthorized = AUTHORIZED_EXPLICIT_SESSION_OR_HANDOFF_STATES.has(normalizeComparable(holderState));
62
- if (!assignmentAuthorized) return deepFreeze({
45
+ if (!isCanonicalHolderAssignmentMode(requestedMode)) return deepFreeze({
63
46
  state: 'unresolved',
64
- assignmentMode: '',
47
+ assignmentMode: requestedMode,
48
+ authorizedModes: deepFreeze([...(modeAuthority.modes || [])]),
49
+ holderState,
50
+ source: modeAuthority.source,
51
+ reasonCode: 'holder-binding-assertion-mode-unqualified',
52
+ modeAuthority,
53
+ provenance,
54
+ boundary: 'The asserted binding mechanism is not a canonical mode established by semantic authority. Core does not reinterpret arbitrary assertion labels.'
55
+ });
56
+
57
+ if (!(modeAuthority.modes || []).includes(requestedMode)) return deepFreeze({
58
+ state: 'unresolved',
59
+ assignmentMode: requestedMode,
60
+ authorizedModes: deepFreeze([...(modeAuthority.modes || [])]),
65
61
  holderState,
66
- source: 'qualified-recipient-role-material',
67
- reasonCode: holderState ? 'holder-assignment-mode-not-authorized' : 'holder-assignment-mode-unresolved',
62
+ source: modeAuthority.source,
63
+ reasonCode: 'holder-assignment-mode-not-authorized',
64
+ modeAuthority,
68
65
  provenance,
69
- boundary: 'The exact qualified Role does not establish authorization for explicit-session/Handoff assignment. Core preserves this as unresolved and does not reinterpret other Holder State wording.'
66
+ boundary: 'The exact qualified canonical mode set does not authorize the asserted bounded binding mechanism. No widening between session, user-session, invocation, Handoff, or participation modes is permitted.'
70
67
  });
71
68
 
72
69
  return deepFreeze({
73
70
  state: 'qualified',
74
- assignmentMode: 'explicit-session-or-handoff',
71
+ assignmentMode: requestedMode,
72
+ authorizedModes: deepFreeze([...(modeAuthority.modes || [])]),
75
73
  holderState,
76
- source: 'qualified-recipient-role-material',
74
+ source: modeAuthority.source,
77
75
  reasonCode: 'holder-assignment-mode-authorized',
76
+ modeAuthority,
78
77
  provenance,
79
- boundary: 'Exact qualified Role Holder Relationship authorizes this assignment mode for the bounded current session only; it does not establish durable holder identity or broader participant/process/source authority.'
78
+ boundary: 'Exact qualified canonical assignment-mode authority authorizes only this bounded assertion mechanism; it does not establish durable holder identity or broader participant/process/delegation/source/acceptance authority.'
80
79
  });
81
80
  }
@@ -41,6 +41,7 @@ export function projectPortableGroundingReadiness(input = {}, options = {}) {
41
41
  route,
42
42
  toolingAvailable: true
43
43
  }, { ...options, coldStartMaterialContext: materialContext });
44
+ const authority = withExplicitGroundingAuthorityInputs(grounding, input);
44
45
  const continuation = projectGroundedContinuation({
45
46
  bundle,
46
47
  route,
@@ -62,7 +63,7 @@ export function projectPortableGroundingReadiness(input = {}, options = {}) {
62
63
  });
63
64
  return composeGroundingReadiness({
64
65
  mode: 'routed-handoff-package',
65
- authority: grounding,
66
+ authority,
66
67
  continuation,
67
68
  contextAudit,
68
69
  material,
@@ -140,8 +141,8 @@ export function composeGroundingReadiness({ mode = 'loaded-material', authority
140
141
  known.push(evidence('session-holder-role-binding-authorization', 'qualified', authority?.holderBinding?.authorization?.provenance?.roleArtifactPath || authority?.role?.endpoint?.label || 'recipient Role material'));
141
142
  } else {
142
143
  holderBindingActReady = false;
143
- unresolved.push(evidence('session-holder-role-binding-authorization', holderAuthorizationState || 'unresolved', authority?.holderBinding?.authorization?.holderState || 'exact qualified Role Holder Relationship does not establish the explicit-session/Handoff assignment mode'));
144
- reasons.push(reason('session-holder-role-binding-authorization-unresolved', 'The explicit consuming-session Role assertion matches the selected recipient Role, but exact qualified Role holder-assignment authority does not establish that assignment mode. Matching session input alone cannot make the route act-ready.'));
144
+ unresolved.push(evidence('session-holder-role-binding-authorization', holderAuthorizationState || 'unresolved', authority?.holderBinding?.authorization?.reasonCode || 'exact qualified canonical assignment-mode authority does not authorize the asserted binding mechanism'));
145
+ reasons.push(reason('session-holder-role-binding-authorization-unresolved', 'The explicit consuming-session Role assertion matches the selected recipient Role, but exact qualified canonical assignment-mode authority does not authorize the asserted mechanism. Matching session input alone cannot make the route act-ready.'));
145
146
  }
146
147
  }
147
148
 
@@ -254,6 +255,7 @@ export function composeGroundingReadiness({ mode = 'loaded-material', authority
254
255
  }),
255
256
  continuity,
256
257
  orchestrationReadiness,
258
+ delegationReadiness: capsule.delegationReadiness,
257
259
  capsule,
258
260
  currentWork: Object.freeze({
259
261
  state: topology.currentFrontier.length ? 'current-frontier-resolved' : topology.currentTasks.length ? 'current-candidates-without-frontier' : 'unresolved',
@@ -288,6 +290,20 @@ export function composeGroundingReadiness({ mode = 'loaded-material', authority
288
290
  });
289
291
  }
290
292
 
293
+
294
+ function withExplicitGroundingAuthorityInputs(grounding = {}, input = {}) {
295
+ const context = input.delegationContext && typeof input.delegationContext === 'object' ? input.delegationContext : {};
296
+ const selected = {
297
+ delegateCapabilityAuthority: input.delegateCapabilityAuthority || context.delegateCapabilityAuthority || null,
298
+ processApplicability: input.processApplicability || context.processApplicability || null,
299
+ delegationTargetAuthority: input.delegationTargetAuthority || context.delegationTargetAuthority || context.targetAuthority || null,
300
+ implementationSourceAuthority: input.implementationSourceAuthority || context.implementationSourceAuthority || context.sourceAuthority || null,
301
+ delegationReturnReconciliationExpectation: input.delegationReturnReconciliationExpectation || context.delegationReturnReconciliationExpectation || context.returnReconciliationExpectation || null
302
+ };
303
+ const additions = Object.fromEntries(Object.entries(selected).filter(([, value]) => value && typeof value === 'object'));
304
+ return Object.freeze({ ...(grounding || {}), ...additions, ...(Object.keys(context).length ? { delegationContext: Object.freeze({ ...context }) } : {}) });
305
+ }
306
+
291
307
  function projectWorkspaceActionCoverage(contextAudit = {}) {
292
308
  const workspaces = Array.isArray(contextAudit?.workspaceMaterializations) ? contextAudit.workspaceMaterializations : [];
293
309
  const summaries = workspaces.map((workspace) => {
@@ -174,7 +174,7 @@ export function resolveRequiredContextRecords(requiredContext = [], records = []
174
174
  }
175
175
 
176
176
  function isExactHydratedWorkspaceContext(entry = {}) {
177
- if (String(entry.providerMode || '') !== 'archive') return false;
177
+ if (!['archive', 'cache'].includes(String(entry.providerMode || ''))) return false;
178
178
  if (!['hydrated-text', 'qualified-locator-only'].includes(String(entry.contentState || ''))) return false;
179
179
  const expectedBytes = Number(entry.bytes || 0);
180
180
  const actualBytes = Number(entry.actualBytes || 0);
@@ -71,8 +71,22 @@ function qualifyRequiredRequirement(bundle, descriptor, byteProvider, workspace,
71
71
  let resolution=null;
72
72
  if (!target||target.startsWith('#')) { resolution=resolveDescriptorMaterial(bundle,descriptor,byteProvider,target,requirementId,workspace.id,routePath); if(!resolution) reasons.push('exact-required-material-reference-or-binding-unresolved'); }
73
73
  const qualified=parseWorkspaceQualifiedReference(target);
74
- if (!resolution&&!reasons.length&&qualified) resolution=resolveWorkspaceRequiredMaterial(byteProvider,{id:qualified.workspaceId},qualified.path);
75
- if (!resolution&&!reasons.length&&!qualified&&!isExternalReference(target)) { const resolvedPath=resolveWorkspaceReference(routePath,target); if(!resolvedPath) reasons.push('workspace-reference-outside-or-invalid'); else resolution=resolveWorkspaceRequiredMaterial(byteProvider,workspace,resolvedPath); }
74
+ if (!resolution&&!reasons.length&&qualified) {
75
+ const workspaceResolution=resolveWorkspaceRequiredMaterial(byteProvider,{id:qualified.workspaceId},qualified.path);
76
+ resolution=workspaceResolution.state==='qualified'
77
+ ? workspaceResolution
78
+ : (resolveDescriptorMaterial(bundle,descriptor,byteProvider,target,requirementId,workspace.id,routePath)||workspaceResolution);
79
+ }
80
+ if (!resolution&&!reasons.length&&!qualified&&!isExternalReference(target)) {
81
+ const resolvedPath=resolveWorkspaceReference(routePath,target);
82
+ if(!resolvedPath) reasons.push('workspace-reference-outside-or-invalid');
83
+ else {
84
+ const workspaceResolution=resolveWorkspaceRequiredMaterial(byteProvider,workspace,resolvedPath);
85
+ resolution=workspaceResolution.state==='qualified'
86
+ ? workspaceResolution
87
+ : (resolveDescriptorMaterial(bundle,descriptor,byteProvider,target,requirementId,workspace.id,routePath)||workspaceResolution);
88
+ }
89
+ }
76
90
  if (!resolution&&!reasons.length) resolution=resolveDescriptorMaterial(bundle,descriptor,byteProvider,target,requirementId,workspace.id,routePath);
77
91
  if (!resolution&&!reasons.length) reasons.push('required-material-not-carried');
78
92
  if (resolution?.state!=='qualified'&&resolution?.reason) reasons.push(resolution.reason);
@@ -190,8 +204,10 @@ function resolveRouteParent(bundle, descriptor, byteProvider, workspace, routePa
190
204
  if (!markdown) continue;
191
205
  const self = validatedC14nV2PrimarySelfDigest(markdown);
192
206
  if (self.state !== 'verified' || self.value !== digest) continue;
193
- const key = `${candidate.workspaceId || ''}\u0000${candidate.workspaceRelativePath || ''}\u0000${candidate.packagePath || ''}`;
194
- digestMatches.set(key, Object.freeze({ state: 'qualified', markdown, basis: 'parent-target-digest-candidate', workspaceRelativePath: normalizeWorkspacePath(candidate.workspaceRelativePath || ''), packagePath: String(candidate.packagePath || ''), sha256: sha256Hex(data) }));
207
+ const candidatePath = normalizeWorkspacePath(candidate.workspaceRelativePath || '');
208
+ const candidateSha256 = sha256Hex(data);
209
+ const key = `${candidate.workspaceId || ''}\u0000${candidatePath}\u0000${candidateSha256}`;
210
+ if (!digestMatches.has(key)) digestMatches.set(key, Object.freeze({ state: 'qualified', markdown, basis: 'parent-target-digest-candidate', workspaceRelativePath: candidatePath, packagePath: String(candidate.packagePath || ''), sha256: candidateSha256 }));
195
211
  }
196
212
  if (digestMatches.size === 1) return [...digestMatches.values()][0];
197
213
  if (digestMatches.size > 1) return Object.freeze({ state: 'ambiguous', reason: 'multiple-parent-target-digest-candidates' });
@@ -19,6 +19,7 @@ import {
19
19
  resolveGroundingRouteMarkdown,
20
20
  recipientFactsIndexForColdStart,
21
21
  resolveReferencedRoleMaterial,
22
+ resolveReferencedEndpointRoleMaterial,
22
23
  selectGroundingRoute
23
24
  } from './coldStartQualification.materials.js';
24
25
  import {
@@ -60,6 +61,7 @@ export function groundPortableColdConsumer(input = {}, options = {}) {
60
61
 
61
62
  const bundle = input.bundle || input.package || input;
62
63
  const role = groundRecipientRole(input, handoff, bundle, orientation, selectedRoute, findings, materialContext);
64
+ const senderRole = groundSenderRole(handoff, bundle, orientation, selectedRoute, materialContext);
63
65
  const holderBinding = groundHolderBinding(input, handoff, role, findings);
64
66
  const participation = groundParticipation(input, handoff, bundle, orientation, selectedRoute, findings, materialContext);
65
67
  const interaction = groundInteraction(input, handoff);
@@ -84,6 +86,7 @@ export function groundPortableColdConsumer(input = {}, options = {}) {
84
86
  selectedRoute,
85
87
  handoff,
86
88
  role,
89
+ senderRole,
87
90
  holderBinding,
88
91
  participation,
89
92
  interaction,
@@ -120,6 +123,50 @@ export function groundPortableColdConsumer(input = {}, options = {}) {
120
123
  });
121
124
  }
122
125
 
126
+ function groundSenderRole(handoff, bundle, orientation, selectedRoute, materialContext) {
127
+ const fromKind = normalizeToken(handoff.fromKind);
128
+ if (fromKind && fromKind !== 'role') return deepFreeze({
129
+ state: 'not-applicable',
130
+ endpoint: Object.freeze({ label: handoff.from || '', kind: handoff.fromKind || '', bounded: Boolean(handoff.from) }),
131
+ material: Object.freeze({ state: 'not-required', artifact: null }),
132
+ exactBoundaryLoaded: null,
133
+ authorityBoundaryLoaded: null,
134
+ boundary: 'Sender endpoint is not declared as Role; no sender Role authority is invented.'
135
+ });
136
+ if (!handoff.fromReference) return deepFreeze({
137
+ state: 'unresolved',
138
+ endpoint: Object.freeze({ label: handoff.from || '', kind: handoff.fromKind || (handoff.from ? 'role' : ''), bounded: Boolean(handoff.from) }),
139
+ material: Object.freeze({ state: 'missing-exact-reference', artifact: null }),
140
+ exactBoundaryLoaded: null,
141
+ authorityBoundaryLoaded: null,
142
+ boundary: 'Delegation projection requires an exact Handoff From Reference; Role inventory and endpoint labels are not substituted.'
143
+ });
144
+ const localFindings = [];
145
+ const material = resolveReferencedEndpointRoleMaterial(bundle, handoff, orientation, selectedRoute, localFindings, materialContext, 'from');
146
+ const parsed = material ? parseRoleMaterial(material) : null;
147
+ const target = normalizeComparable(handoff.from || '');
148
+ if (!parsed || (target && normalizeComparable(parsed.label) !== target)) return deepFreeze({
149
+ state: 'unresolved',
150
+ endpoint: Object.freeze({ label: handoff.from || '', kind: handoff.fromKind || (handoff.from ? 'role' : ''), bounded: Boolean(handoff.from) }),
151
+ material: Object.freeze({ state: localFindings.length ? 'unresolved-exact-reference' : 'missing', artifact: null }),
152
+ exactBoundaryLoaded: null,
153
+ authorityBoundaryLoaded: null,
154
+ boundary: 'Exact sender Role material did not qualify; sender authority is not inferred from carried Role inventory.'
155
+ });
156
+ return deepFreeze({
157
+ state: 'qualified',
158
+ endpoint: Object.freeze({ label: handoff.from || parsed.label || '', kind: handoff.fromKind || 'role', bounded: Boolean(handoff.from) }),
159
+ material: Object.freeze({
160
+ state: 'qualified',
161
+ artifact: Object.freeze({ path: parsed.path, sha256: parsed.sha256, schemaId: parsed.schemaId, title: parsed.title, roleLabel: parsed.label, roleKind: parsed.roleKind, reference: handoff.fromReference || '' })
162
+ }),
163
+ exactBoundaryLoaded: parsed.boundary,
164
+ authorityBoundaryLoaded: parsed.authorityBoundary,
165
+ interpretationLimitsLoaded: parsed.interpretationLimits,
166
+ boundary: 'Exact Handoff From Reference Role material only. Sender Role authority remains separate from Handoff transfer and is never inferred from endpoint naming or cache inventory.'
167
+ });
168
+ }
169
+
123
170
  function groundRecipientRole(input, handoff, bundle, orientation, selectedRoute, findings, materialContext) {
124
171
  const toKind = normalizeToken(handoff.toKind);
125
172
  if (toKind && toKind !== 'role') return deepFreeze({
@@ -201,12 +248,14 @@ function groundHolderBinding(input, handoff, role, findings) {
201
248
  const roleRecipient = recipientRoleKind === 'role';
202
249
  const explicitlySupplied = Boolean(roleLabel || holderId);
203
250
  const sourceDetail = holderBindingSourceDetail(input, explicit, explicitlySupplied);
204
- const authorization = projectHolderBindingAuthorization(role);
251
+ const assertionMode = String(explicit.assignmentMode || explicit.bindingMode || explicit.mechanism || input.holderAssignmentMode || input.sessionAssignmentMode || 'explicit-session').trim();
252
+ const authorization = projectHolderBindingAuthorization(role, { assertionMode });
205
253
  const durableIdentity = holderDurableIdentityProjection(holderId);
206
254
 
207
255
  if (!roleRecipient) return deepFreeze({
208
256
  state: 'not-applicable',
209
257
  holderId,
258
+ assertionMode,
210
259
  roleLabel,
211
260
  recipientRoleLabel,
212
261
  recipientCompatibility: 'not-applicable',
@@ -224,6 +273,7 @@ function groundHolderBinding(input, handoff, role, findings) {
224
273
  return deepFreeze({
225
274
  state: 'unresolved',
226
275
  holderId,
276
+ assertionMode,
227
277
  roleLabel: '',
228
278
  recipientRoleLabel,
229
279
  recipientCompatibility: 'unresolved',
@@ -242,6 +292,7 @@ function groundHolderBinding(input, handoff, role, findings) {
242
292
  return deepFreeze({
243
293
  state: 'blocked',
244
294
  holderId,
295
+ assertionMode,
245
296
  roleLabel,
246
297
  recipientRoleLabel,
247
298
  recipientCompatibility: 'mismatch',
@@ -258,6 +309,7 @@ function groundHolderBinding(input, handoff, role, findings) {
258
309
  return deepFreeze({
259
310
  state: 'qualified',
260
311
  holderId,
312
+ assertionMode,
261
313
  roleLabel,
262
314
  recipientRoleLabel,
263
315
  recipientCompatibility: 'matched',
@@ -310,7 +362,7 @@ function holderBindingSourceDetail(input = {}, explicit = {}, explicitlySupplied
310
362
 
311
363
  function groundParticipation(input, handoff, bundle, orientation, selectedRoute, findings, materialContext) {
312
364
  const explicitParticipants = normalizeParticipants(input.participants || input.interaction?.participants || []);
313
- const packageRoleGrounding = resolvePackageParticipantRoles(bundle, orientation, selectedRoute, findings);
365
+ const packageRoleGrounding = resolvePackageParticipantRoles(bundle, orientation, selectedRoute, findings, materialContext);
314
366
  const participants = dedupeGroundedParticipants(explicitParticipants);
315
367
  const contributions = normalizeContributions(input.contributions || input.interaction?.contributions || []);
316
368
  const currentContributionId = String(input.currentContributionId || input.interaction?.currentContributionId || '').trim();
@@ -345,7 +397,7 @@ function resolvePackageParticipantRoles(bundle = {}, orientation = null, selecte
345
397
  const pointerPath = String(pointerPaths[index] || '');
346
398
  const pointerFile = findFile(bundle, pointerPath);
347
399
  if (!pointerFile) { findings.push(portableFinding('error', 'portable.cold-start.participant-role.pointer.missing', 'Selected Handoff route declares Role grounding Pointer ancestry that is not carried.', { pointerPath })); continue; }
348
- const compatibilityFacts = recipientV2FactsIndex(bundle).map.get(pointerPath) || null;
400
+ const compatibilityFacts = recipientFactsIndexForColdStart(bundle, materialContext).map.get(pointerPath) || null;
349
401
  const projectedFacts = (orientation?.participantRoles || []).find((item) => String(item.pointerPath || '') === pointerPath) || null;
350
402
  const facts = compatibilityFacts?.role === 'participant-role'
351
403
  ? compatibilityFacts
@@ -370,7 +422,18 @@ function resolvePackageParticipantRoles(bundle = {}, orientation = null, selecte
370
422
  packageDeclared: true,
371
423
  groundingOnly: true,
372
424
  semanticParticipant: false,
373
- roleArtifact: Object.freeze({ path: parsed.path, sha256: parsed.sha256, schemaId: parsed.schemaId, roleLabel: parsed.label, roleKind: parsed.roleKind }),
425
+ materialQualification: 'qualified',
426
+ roleArtifact: Object.freeze({
427
+ path: parsed.path,
428
+ reference: String(facts.referenceTarget || parsed.path || ''),
429
+ sha256: parsed.sha256,
430
+ schemaId: parsed.schemaId,
431
+ roleLabel: parsed.label,
432
+ roleKind: parsed.roleKind
433
+ }),
434
+ exactBoundaryLoaded: parsed.boundary,
435
+ authorityBoundaryLoaded: parsed.authorityBoundary,
436
+ interpretationLimitsLoaded: parsed.interpretationLimits,
374
437
  pointerPath
375
438
  }));
376
439
  }