@inf-monkeys-tech/monkeys 1.0.68 → 1.0.69

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 (37) hide show
  1. package/lib/contracts/declarative-control-http.d.ts +1681 -369
  2. package/lib/contracts/declarative-control-http.d.ts.map +1 -1
  3. package/lib/contracts/declarative-control.d.ts +740 -23
  4. package/lib/contracts/declarative-control.d.ts.map +1 -1
  5. package/lib/contracts/declarative-control.js +22 -3
  6. package/lib/contracts/declarative-control.js.map +1 -1
  7. package/lib/esm/contracts/index.mjs +22 -3
  8. package/lib/esm/contracts/index.mjs.map +1 -1
  9. package/lib/esm/index.mjs +98 -3
  10. package/lib/esm/index.mjs.map +1 -1
  11. package/lib/esm/runtime/index.mjs +97 -3
  12. package/lib/esm/runtime/index.mjs.map +1 -1
  13. package/lib/esm/schemas/index.mjs +22 -3
  14. package/lib/esm/schemas/index.mjs.map +1 -1
  15. package/lib/json-schema/navigation-release.schema.json +582 -0
  16. package/lib/json-schema/navigation-runtime-bundle.schema.json +579 -0
  17. package/lib/runtime/declarative-control-compiler.d.ts.map +1 -1
  18. package/lib/runtime/declarative-control-compiler.js +26 -0
  19. package/lib/runtime/declarative-control-compiler.js.map +1 -1
  20. package/lib/runtime/index.d.ts +1 -0
  21. package/lib/runtime/index.d.ts.map +1 -1
  22. package/lib/runtime/index.js +1 -0
  23. package/lib/runtime/index.js.map +1 -1
  24. package/lib/runtime/menu-compiler.d.ts +19 -1
  25. package/lib/runtime/menu-compiler.d.ts.map +1 -1
  26. package/lib/runtime/menu-compiler.js +34 -0
  27. package/lib/runtime/menu-compiler.js.map +1 -1
  28. package/lib/runtime/navigation-availability.d.ts +6 -0
  29. package/lib/runtime/navigation-availability.d.ts.map +1 -0
  30. package/lib/runtime/navigation-availability.js +17 -0
  31. package/lib/runtime/navigation-availability.js.map +1 -0
  32. package/lib/schemas/index.d.ts +240 -1
  33. package/lib/schemas/index.d.ts.map +1 -1
  34. package/lib/schemas/index.js +5 -4
  35. package/lib/schemas/index.js.map +1 -1
  36. package/package.json +1 -1
  37. package/test/fixtures/navigation-three-roots-topology.json +275 -0
@@ -10076,6 +10076,12 @@ var ResolvedNavigationTargetSchema = z9.object({
10076
10076
  targetRevisionRef: RevisionRefSchema,
10077
10077
  releaseRevisionRef: RevisionRefSchema.optional()
10078
10078
  }).strict();
10079
+ var UnavailableNavigationTargetSchema = z9.object({
10080
+ nodeId: ContractIdentifierSchema,
10081
+ stableTargetRef: StableRefSchema.refine((reference) => reference.kind === "page", "Only missing Pages can be isolated."),
10082
+ reason: z9.literal("page-missing"),
10083
+ accessPolicy: AccessPolicySchema.nullable()
10084
+ }).strict();
10079
10085
  var NavigationReleaseSchema = z9.object({
10080
10086
  contract: z9.literal("NavigationRelease"),
10081
10087
  ...ReleaseBaseShape,
@@ -10085,13 +10091,17 @@ var NavigationReleaseSchema = z9.object({
10085
10091
  surface: ProductSurfaceSchema,
10086
10092
  placement: ContractIdentifierSchema
10087
10093
  }).strict(),
10088
- resolvedTargets: z9.array(ResolvedNavigationTargetSchema)
10094
+ resolvedTargets: z9.array(ResolvedNavigationTargetSchema),
10095
+ unavailableTargets: z9.array(UnavailableNavigationTargetSchema).optional()
10089
10096
  }).strict().superRefine((value, context) => {
10090
10097
  validateDependencySnapshot(value.dependencySnapshot, context);
10091
10098
  validateReleaseExpectedHead(value, "navigation-release", context);
10092
10099
  if (value.navigationRevisionRef.kind !== "navigation") context.addIssue({ code: "custom", path: ["navigationRevisionRef", "kind"], message: "Expected a navigation revision." });
10093
10100
  if (value.target.environmentRef.kind !== "environment") context.addIssue({ code: "custom", path: ["target", "environmentRef", "kind"], message: "Navigation release target requires an environment reference." });
10094
10101
  if (uniqueArray(value.resolvedTargets, (target) => target.nodeId)) context.addIssue({ code: "custom", path: ["resolvedTargets"], message: "Resolved Navigation node IDs must be unique." });
10102
+ if (uniqueArray([...value.resolvedTargets, ...value.unavailableTargets ?? []], (target) => target.nodeId)) {
10103
+ context.addIssue({ code: "custom", path: ["unavailableTargets"], message: "Navigation target resolutions must have unique node IDs." });
10104
+ }
10095
10105
  });
10096
10106
  var RuntimeDiagnosticSchema = z9.object({
10097
10107
  code: ContractIdentifierSchema,
@@ -10179,7 +10189,8 @@ var CompiledNavigationDomainCommandTargetSchema = ResolvedNavigationTargetSchema
10179
10189
  var CompiledNavigationResolvedTargetSchema = z9.discriminatedUnion("kind", [
10180
10190
  CompiledNavigationTargetSchema,
10181
10191
  CompiledNavigationRegisteredMenuActionTargetSchema,
10182
- CompiledNavigationDomainCommandTargetSchema
10192
+ CompiledNavigationDomainCommandTargetSchema,
10193
+ UnavailableNavigationTargetSchema.omit({ reason: true }).extend({ kind: z9.literal("unavailable") }).strict()
10183
10194
  ]);
10184
10195
  var CompiledNavigationGroupNodeSchema = NavigationGroupNodeSchema.extend({
10185
10196
  ancestorAccessPolicies: z9.array(AccessPolicySchema)
@@ -10187,7 +10198,14 @@ var CompiledNavigationGroupNodeSchema = NavigationGroupNodeSchema.extend({
10187
10198
  var CompiledNavigationTargetNodeSchema = NavigationTargetNodeSchema.extend({
10188
10199
  ancestorAccessPolicies: z9.array(AccessPolicySchema),
10189
10200
  resolvedTarget: CompiledNavigationResolvedTargetSchema
10190
- }).strict();
10201
+ }).strict().superRefine((node, context) => {
10202
+ if (node.resolvedTarget.nodeId !== node.nodeId || stableRefIdentity(node.resolvedTarget.stableTargetRef) !== stableRefIdentity(node.targetRef)) {
10203
+ context.addIssue({ code: "custom", path: ["resolvedTarget"], message: "Resolved target identity must match the source node." });
10204
+ }
10205
+ if (node.resolvedTarget.kind === "unavailable" && (node.disabled !== true || Object.keys(node.parameterMapping).length > 0)) {
10206
+ context.addIssue({ code: "custom", path: ["resolvedTarget"], message: "Unavailable targets must be disabled and contain no executable input." });
10207
+ }
10208
+ });
10191
10209
  var CompiledNavigationSeparatorNodeSchema = NavigationSeparatorNodeSchema.extend({
10192
10210
  ancestorAccessPolicies: z9.array(AccessPolicySchema)
10193
10211
  }).strict();
@@ -11407,7 +11425,14 @@ var compileNavigationRuntimeBundle = (input) => {
11407
11425
  assertUniqueRegistryKeys(targetRegistry.map((registration) => stableRefKey(registration.stableTargetRef)), "targetRegistry");
11408
11426
  const targetsByStableRef = new Map(targetRegistry.map((registration) => [stableRefKey(registration.stableTargetRef), registration]));
11409
11427
  const releasedByNodeId = new Map(release.resolvedTargets.map((target) => [target.nodeId, target]));
11428
+ const unavailableByNodeId = new Map((release.unavailableTargets ?? []).map((target) => [target.nodeId, target]));
11410
11429
  const nodesById = new Map(navigation.nodes.map((node) => [node.nodeId, node]));
11430
+ for (const target of release.unavailableTargets ?? []) {
11431
+ const node = nodesById.get(target.nodeId);
11432
+ if (node?.kind !== "target" || !sameStableRef(node.targetRef, target.stableTargetRef)) {
11433
+ throw new DeclarativeControlCompilationError("NAV_TARGET_UNRELEASED", "release.unavailableTargets", "An unavailable target must identify its source Page node exactly.");
11434
+ }
11435
+ }
11411
11436
  const nodes = orderedNavigationNodes(navigation).map((node, index) => {
11412
11437
  const ancestors = [];
11413
11438
  let parentId = node.parentNodeId;
@@ -11422,6 +11447,25 @@ var compileNavigationRuntimeBundle = (input) => {
11422
11447
  }
11423
11448
  const registration = targetsByStableRef.get(stableRefKey(node.targetRef));
11424
11449
  const released = releasedByNodeId.get(node.nodeId);
11450
+ const unavailable = unavailableByNodeId.get(node.nodeId);
11451
+ if (!registration && unavailable && node.targetRef.kind === "page" && sameStableRef(unavailable.stableTargetRef, node.targetRef)) {
11452
+ assertTenantCompatible(node.targetRef, scope, `nodes[${index}].targetRef`);
11453
+ if (unavailable.accessPolicy && !accessPolicyChainImplies([...ancestors, node.audience], unavailable.accessPolicy)) {
11454
+ throw new DeclarativeControlCompilationError("AUDIENCE_WIDER_THAN_TARGET", `nodes[${index}].audience`, "Effective Navigation audience is wider than the last verified target audience.");
11455
+ }
11456
+ return {
11457
+ ...node,
11458
+ disabled: true,
11459
+ parameterMapping: {},
11460
+ ancestorAccessPolicies: ancestors,
11461
+ resolvedTarget: {
11462
+ kind: "unavailable",
11463
+ nodeId: node.nodeId,
11464
+ stableTargetRef: node.targetRef,
11465
+ accessPolicy: unavailable.accessPolicy
11466
+ }
11467
+ };
11468
+ }
11425
11469
  if (!registration || !released || !sameStableRef(registration.stableTargetRef, stableFromRevision(registration.targetRevisionRef)) || !sameStableRef(registration.stableTargetRef, released.stableTargetRef) || !sameRevisionRef(registration.targetRevisionRef, released.targetRevisionRef) || registration.kind === "route" && (Boolean(registration.releaseRevisionRef) !== Boolean(released.releaseRevisionRef) || registration.releaseRevisionRef && released.releaseRevisionRef && !sameRevisionRef(registration.releaseRevisionRef, released.releaseRevisionRef))) {
11426
11470
  throw new DeclarativeControlCompilationError("NAV_TARGET_UNRELEASED", `nodes[${index}].targetRef`, "Navigation target is not resolved to the exact active release recorded by NavigationRelease.");
11427
11471
  }
@@ -11551,6 +11595,16 @@ var resolveWorkbenchEntry = (input) => {
11551
11595
  return { status: "forbidden", workbenchId: "" };
11552
11596
  };
11553
11597
 
11598
+ // src/runtime/navigation-availability.ts
11599
+ var NAVIGATION_UNAVAILABLE_CAPABILITY_HEADER = "x-monkeys-navigation-capabilities";
11600
+ var NAVIGATION_UNAVAILABLE_CAPABILITY = "unavailable-pages-v1";
11601
+ function projectNavigationCompatibility(bundle, supportsUnavailable) {
11602
+ if (supportsUnavailable || !bundle.nodes.some((node) => node.kind === "target" && node.resolvedTarget.kind === "unavailable")) return bundle;
11603
+ const { contentHash: _hash, ...unsigned } = bundle;
11604
+ const nodes = bundle.nodes.filter((node) => node.kind !== "target" || node.resolvedTarget.kind !== "unavailable");
11605
+ return NavigationRuntimeBundleSchema.parse({ ...unsigned, nodes, contentHash: canonicalContentHash({ ...unsigned, nodes }) });
11606
+ }
11607
+
11554
11608
  // src/runtime/menu-compiler.ts
11555
11609
  var MenuCompilationError = class extends Error {
11556
11610
  constructor(code, path, message) {
@@ -11823,6 +11877,13 @@ var compileMenuRuntimeBundle = (input) => {
11823
11877
  const contributionProviders = input.contributionProviders.map((registration) => MenuContributionProviderRegistrationSchema.parse(registration));
11824
11878
  const inputValidators = input.inputValidators ?? /* @__PURE__ */ new Map();
11825
11879
  const knownPermissions = new Set(input.permissionCodes.map((permission) => ContractIdentifierSchema.parse(permission)));
11880
+ const completeApplications = new Set(input.missingPagePolicy?.completeApplicationIds.map((id) => ContractIdentifierSchema.parse(id)) ?? []);
11881
+ const unavailableAccess = input.missingPagePolicy ? MenuAccessRequirementSchema.parse(input.missingPagePolicy.unavailableAccess) : void 0;
11882
+ if (unavailableAccess) {
11883
+ validatePermissionCodes(unavailableAccess.permissionAllOf, knownPermissions, "missingPagePolicy.unavailableAccess.permissionAllOf");
11884
+ validatePermissionCodes(unavailableAccess.permissionAnyOf, knownPermissions, "missingPagePolicy.unavailableAccess.permissionAnyOf");
11885
+ }
11886
+ const diagnostics = [];
11826
11887
  pages.forEach((registration, index) => {
11827
11888
  if (!registration.page.visibility.productContexts.some((context) => context === registration.applicationId)) {
11828
11889
  throw new MenuCompilationError(
@@ -11887,6 +11948,35 @@ var compileMenuRuntimeBundle = (input) => {
11887
11948
  if (node.behavior.kind === "navigate") {
11888
11949
  const registration = pagesByKey.get(pageKey(node.behavior.page));
11889
11950
  if (!registration) {
11951
+ if (unavailableAccess && completeApplications.has(node.behavior.page.applicationId)) {
11952
+ const activationId2 = resolveMenuActivationId(node.behavior.page, node.behavior.activationId);
11953
+ const identity2 = targetKey(node.behavior.page, activationId2);
11954
+ const signature2 = stableSerialize2({ ...node.behavior, activationId: activationId2 });
11955
+ const previous = targetSourceSignatures.get(identity2);
11956
+ if (previous !== void 0 && previous !== signature2) {
11957
+ throw new MenuCompilationError("conflicting-navigation-target", `${nodePath}.behavior`, "Missing navigation target has conflicting behavior or input.");
11958
+ }
11959
+ targetSourceSignatures.set(identity2, signature2);
11960
+ if (definition.applicationId === applicationId) {
11961
+ diagnostics.push({
11962
+ code: "missing-page",
11963
+ severity: "warning",
11964
+ applicationId: definition.applicationId,
11965
+ surface: definition.surface,
11966
+ menuId: definition.menuId,
11967
+ nodeId: node.nodeId,
11968
+ page: node.behavior.page,
11969
+ path: `${nodePath}.behavior.page`
11970
+ });
11971
+ }
11972
+ const { requiredPermission: requiredPermission3, behavior: _behavior3, ...presentation3 } = node;
11973
+ return CompiledMenuItemNodeSchema.parse({
11974
+ ...presentation3,
11975
+ disabled: true,
11976
+ behavior: { kind: "navigate", page: node.behavior.page, activationId: activationId2 },
11977
+ access: { ...unavailableAccess, requiredPermission: requiredPermission3 }
11978
+ });
11979
+ }
11890
11980
  throw new MenuCompilationError(
11891
11981
  "unknown-page",
11892
11982
  `${nodePath}.behavior.page`,
@@ -12049,6 +12139,7 @@ var compileMenuRuntimeBundle = (input) => {
12049
12139
  };
12050
12140
  return Object.freeze({
12051
12141
  document: deepFreeze2(document),
12142
+ diagnostics: deepFreeze2(diagnostics),
12052
12143
  menusByKey,
12053
12144
  navigationTargetsByKey: documentTargetsByKey,
12054
12145
  serverInputByTargetKey,
@@ -15852,6 +15943,8 @@ export {
15852
15943
  DeclarativeControlCompilationError,
15853
15944
  MONKEYS_REQUIRED_THEME_TOKEN_PATHS,
15854
15945
  MenuCompilationError,
15946
+ NAVIGATION_UNAVAILABLE_CAPABILITY,
15947
+ NAVIGATION_UNAVAILABLE_CAPABILITY_HEADER,
15855
15948
  ThemeTokenValidationError,
15856
15949
  accessPolicyChainImplies,
15857
15950
  applyViewRuntimeBindings,
@@ -15896,6 +15989,7 @@ export {
15896
15989
  mergeThemeTokenDocuments,
15897
15990
  parseApplicationHandoff,
15898
15991
  projectAgentSessionEvents,
15992
+ projectNavigationCompatibility,
15899
15993
  publishOpenApiToolCapabilityManifests,
15900
15994
  readApplicationHandoffFromUrl,
15901
15995
  readMenuActivationFromSearch,