@kehto/shell 0.11.1 → 0.13.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.
package/dist/index.js CHANGED
@@ -893,7 +893,7 @@ var audioManager = {
893
893
  if (iframeWindow) {
894
894
  const muteEvent = {
895
895
  kind: 29e3,
896
- // IFC_PEER — inlined numeric after Phase 24 DRIFT-01 shim removal
896
+ // INC_PEER — inlined numeric after Phase 24 DRIFT-01 shim removal
897
897
  created_at: Math.floor(Date.now() / 1e3),
898
898
  tags: [["t", "napplet:audio-muted"]],
899
899
  content: JSON.stringify({ muted }),
@@ -975,107 +975,7 @@ function createKeysForwarder(deps) {
975
975
  };
976
976
  }
977
977
 
978
- // src/connect-store.ts
979
- var STORAGE_KEY3 = "napplet:connect";
980
- function connectKey(dTag, aggregateHash) {
981
- return `${dTag}:${aggregateHash}`;
982
- }
983
- var store2 = /* @__PURE__ */ new Map();
984
- var connectStore = {
985
- check(dTag, aggregateHash, origin) {
986
- const entry = store2.get(connectKey(dTag, aggregateHash));
987
- if (!entry) return false;
988
- return entry.origins.includes(origin);
989
- },
990
- getOrigins(dTag, aggregateHash) {
991
- const entry = store2.get(connectKey(dTag, aggregateHash));
992
- return entry ? [...entry.origins] : [];
993
- },
994
- grant(dTag, aggregateHash, origins) {
995
- const key = connectKey(dTag, aggregateHash);
996
- const sorted = [...new Set(origins)].sort();
997
- store2.set(key, { key, dTag, aggregateHash, origins: sorted, grantedAt: Date.now() });
998
- connectStore.persist();
999
- },
1000
- revoke(dTag, aggregateHash) {
1001
- store2.delete(connectKey(dTag, aggregateHash));
1002
- connectStore.persist();
1003
- },
1004
- getAllGrants() {
1005
- return Array.from(store2.values()).map((e) => ({
1006
- dTag: e.dTag,
1007
- aggregateHash: e.aggregateHash,
1008
- origins: [...e.origins]
1009
- }));
1010
- },
1011
- persist() {
1012
- try {
1013
- const entries = Array.from(store2.entries()).map(([k, v]) => [k, {
1014
- dTag: v.dTag,
1015
- aggregateHash: v.aggregateHash,
1016
- origins: v.origins,
1017
- grantedAt: v.grantedAt
1018
- }]);
1019
- localStorage.setItem(STORAGE_KEY3, JSON.stringify(entries));
1020
- } catch {
1021
- }
1022
- },
1023
- load() {
1024
- try {
1025
- const raw = localStorage.getItem(STORAGE_KEY3);
1026
- if (!raw) return;
1027
- const entries = JSON.parse(raw);
1028
- store2.clear();
1029
- for (const [key, val] of entries) {
1030
- if (!Array.isArray(val.origins)) continue;
1031
- store2.set(key, {
1032
- key,
1033
- dTag: val.dTag,
1034
- aggregateHash: val.aggregateHash,
1035
- origins: [...val.origins],
1036
- grantedAt: val.grantedAt ?? 0
1037
- });
1038
- }
1039
- } catch {
1040
- store2.clear();
1041
- }
1042
- },
1043
- clear() {
1044
- store2.clear();
1045
- try {
1046
- localStorage.removeItem(STORAGE_KEY3);
1047
- } catch {
1048
- }
1049
- }
1050
- };
1051
- function connectGrantKey(dTag, aggregateHash) {
1052
- return `${dTag}:${aggregateHash}`;
1053
- }
1054
-
1055
978
  // src/shell-init.ts
1056
- var LEGACY_NUB_DOMAINS = [
1057
- "identity",
1058
- "storage",
1059
- "ifc",
1060
- "theme",
1061
- "keys",
1062
- "media",
1063
- "notify",
1064
- "config",
1065
- "resource",
1066
- "connect",
1067
- "class",
1068
- "cvm"
1069
- ];
1070
- var LEGACY_IFC_PROTOCOLS = [
1071
- "ifc:NAP-01",
1072
- "ifc:NUB-01",
1073
- "ifc:NUB-02",
1074
- "ifc:NUB-03",
1075
- "ifc:NUB-04",
1076
- "ifc:NUB-05",
1077
- "ifc:NUB-06"
1078
- ];
1079
979
  var NAP_DOMAINS = [
1080
980
  "identity",
1081
981
  "storage",
@@ -1086,8 +986,6 @@ var NAP_DOMAINS = [
1086
986
  "notify",
1087
987
  "config",
1088
988
  "resource",
1089
- "connect",
1090
- "class",
1091
989
  "cvm"
1092
990
  ];
1093
991
  var NAP_INC_PROTOCOLS = [
@@ -1112,10 +1010,24 @@ function buildShellCapabilities(hooks) {
1112
1010
  const naps = hooks.relayPool ? ["relay", "outbox", ...NAP_DOMAINS, ...NAP_INC_PROTOCOLS] : [...NAP_DOMAINS, ...NAP_INC_PROTOCOLS];
1113
1011
  if (hooks.upload) naps.push("upload");
1114
1012
  if (hooks.intent?.isAvailable()) naps.push("intent");
1115
- const nubs = hooks.relayPool ? ["relay", "outbox", ...LEGACY_NUB_DOMAINS, ...LEGACY_IFC_PROTOCOLS] : [...LEGACY_NUB_DOMAINS, ...LEGACY_IFC_PROTOCOLS];
1116
- if (hooks.upload) nubs.push("upload");
1117
- if (hooks.intent?.isAvailable()) nubs.push("intent");
1118
- return { domains, protocols, naps, nubs, sandbox };
1013
+ return applyCapabilityOverrides(
1014
+ { domains, protocols, naps, sandbox },
1015
+ hooks.capabilities?.disabledDomains ?? []
1016
+ );
1017
+ }
1018
+ function applyCapabilityOverrides(capabilities, disabledDomains) {
1019
+ if (disabledDomains.length === 0) return capabilities;
1020
+ const disabled = new Set(disabledDomains);
1021
+ const protocols = {};
1022
+ for (const [domain, supportedProtocols] of Object.entries(capabilities.protocols)) {
1023
+ if (!disabled.has(domain)) protocols[domain] = supportedProtocols;
1024
+ }
1025
+ return {
1026
+ domains: capabilities.domains.filter((entry) => !disabled.has(entry)),
1027
+ protocols,
1028
+ naps: capabilities.naps.filter((entry) => !disabled.has(entry.split(":")[0] ?? entry)),
1029
+ sandbox: capabilities.sandbox
1030
+ };
1119
1031
  }
1120
1032
 
1121
1033
  // src/shell-ready.ts
@@ -1131,7 +1043,7 @@ function handleShellReady({
1131
1043
  return;
1132
1044
  }
1133
1045
  const capabilities = buildShellCapabilities(hooks);
1134
- postShellInit(runtime, windowId, capabilities, Object.keys(hooks.services ?? {}));
1046
+ postShellInit(windowId, capabilities, Object.keys(hooks.services ?? {}));
1135
1047
  initSent.add(windowId);
1136
1048
  }
1137
1049
  function registerNip5dSessionIfNeeded({
@@ -1156,8 +1068,7 @@ function registerNip5dSessionIfNeeded({
1156
1068
  aggregateHash: identity.aggregateHash,
1157
1069
  registeredAt: Date.now(),
1158
1070
  instanceId: crypto.randomUUID(),
1159
- provenance: "nip-5d",
1160
- class: identity.class
1071
+ provenance: "nip-5d"
1161
1072
  };
1162
1073
  runtime.sessionRegistry.register(windowId, entry);
1163
1074
  }
@@ -1166,8 +1077,7 @@ function resolveNip5dIdentity(hooks, windowId) {
1166
1077
  if (hookIdentity !== null && hookIdentity !== void 0) {
1167
1078
  return {
1168
1079
  dTag: hookIdentity.dTag,
1169
- aggregateHash: hookIdentity.aggregateHash,
1170
- class: hookIdentity.class
1080
+ aggregateHash: hookIdentity.aggregateHash
1171
1081
  };
1172
1082
  }
1173
1083
  const win = originRegistry.getIframeWindow(windowId);
@@ -1180,30 +1090,29 @@ function resolveNip5dIdentity(hooks, windowId) {
1180
1090
  }
1181
1091
  return {
1182
1092
  dTag: originIdentity.dTag,
1183
- aggregateHash: originIdentity.aggregateHash,
1184
- class: null
1093
+ aggregateHash: originIdentity.aggregateHash
1185
1094
  };
1186
1095
  }
1187
- function classToWireCode(c) {
1188
- if (c === null) return null;
1189
- const match = /^class-(\d+)$/.exec(c);
1190
- if (!match) return null;
1191
- return Number.parseInt(match[1], 10);
1192
- }
1193
- function postShellInit(runtime, windowId, capabilities, services) {
1194
- const sessionEntry = runtime.sessionRegistry.getEntryByWindowId(windowId);
1195
- const resolvedClass = sessionEntry?.class ?? null;
1096
+ function postShellInit(windowId, capabilities, services) {
1196
1097
  const initMsg = {
1197
1098
  type: "shell.init",
1198
1099
  capabilities,
1199
- services,
1200
- class: classToWireCode(resolvedClass)
1100
+ services
1201
1101
  };
1202
1102
  const win = originRegistry.getIframeWindow(windowId);
1203
1103
  if (win) win.postMessage(initMsg, "*");
1204
1104
  }
1205
1105
 
1206
1106
  // src/shell-bridge.ts
1107
+ function reportUnrouted(hooks, event, reason) {
1108
+ if (!hooks.onUnroutedMessage) return;
1109
+ const data = event.data;
1110
+ const type = typeof data === "object" && data !== null && typeof data.type === "string" ? data.type : void 0;
1111
+ try {
1112
+ hooks.onUnroutedMessage({ type, origin: event.origin, reason });
1113
+ } catch {
1114
+ }
1115
+ }
1207
1116
  function createShellBridge(hooks) {
1208
1117
  const runtimeHooks = adaptHooks(hooks, {
1209
1118
  originRegistry,
@@ -1241,9 +1150,15 @@ function createShellBridge(hooks) {
1241
1150
  return {
1242
1151
  handleMessage(event) {
1243
1152
  const sourceWindow = event.source;
1244
- if (!sourceWindow) return;
1153
+ if (!sourceWindow) {
1154
+ reportUnrouted(hooks, event, "no-source-window");
1155
+ return;
1156
+ }
1245
1157
  const windowId = originRegistry.getWindowId(sourceWindow);
1246
- if (!windowId) return;
1158
+ if (!windowId) {
1159
+ reportUnrouted(hooks, event, "unregistered-window");
1160
+ return;
1161
+ }
1247
1162
  const msg = event.data;
1248
1163
  if (typeof msg !== "object" || msg === null || typeof msg.type !== "string") return;
1249
1164
  if (msg.type === "shell.ready") {
@@ -1272,16 +1187,13 @@ function createShellBridge(hooks) {
1272
1187
  },
1273
1188
  get runtime() {
1274
1189
  return runtime;
1275
- },
1276
- get connectStore() {
1277
- return connectStore;
1278
1190
  }
1279
1191
  };
1280
1192
  }
1281
1193
 
1282
1194
  // src/index.ts
1283
1195
  import { ALL_CAPABILITIES as ALL_CAPABILITIES2 } from "@kehto/runtime";
1284
- import { createEnforceGate, createNubEnforceGate, formatDenialReason } from "@kehto/runtime";
1196
+ import { createEnforceGate, createNapEnforceGate, formatDenialReason } from "@kehto/runtime";
1285
1197
 
1286
1198
  // src/topics.ts
1287
1199
  import { TOPICS } from "@napplet/core";
@@ -1356,15 +1268,13 @@ export {
1356
1268
  adaptHooks,
1357
1269
  audioManager,
1358
1270
  buildShellCapabilities,
1359
- connectGrantKey,
1360
- connectStore,
1361
1271
  createEnforceGate,
1362
1272
  createIdentityProxy,
1363
1273
  createKeysForwarder,
1364
1274
  createKeysProxy,
1365
1275
  createMediaProxy,
1276
+ createNapEnforceGate,
1366
1277
  createNotifyProxy,
1367
- createNubEnforceGate,
1368
1278
  createShellBridge,
1369
1279
  createThemeProxy,
1370
1280
  formatDenialReason,