@sellable/install 0.1.751 → 0.1.752

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.
@@ -30,6 +30,21 @@ const MAX_FILE_BYTES = 64 * 1024;
30
30
  const MAX_FRAGMENT_BYTES = 192 * 1024;
31
31
  const MAX_TOTAL_BYTES = 1024 * 1024;
32
32
 
33
+ function readNativeSkillName(content) {
34
+ const lines = content.split("\n");
35
+ if (lines[0] !== "---") reject("skill_frontmatter_rejected");
36
+ const end = lines.indexOf("---", 1);
37
+ if (end < 2) reject("skill_frontmatter_rejected");
38
+ const names = lines
39
+ .slice(1, end)
40
+ .map((line) => /^name:\s*([a-z0-9][a-z0-9-]{0,63})\s*$/.exec(line)?.[1])
41
+ .filter(Boolean);
42
+ if (names.length !== 1 || !ID.test(names[0])) {
43
+ reject("skill_frontmatter_rejected");
44
+ }
45
+ return names[0];
46
+ }
47
+
33
48
  function sha256(value) {
34
49
  return createHash("sha256").update(value).digest("hex");
35
50
  }
@@ -200,7 +215,9 @@ function normalizeFile(value, fragmentKind) {
200
215
  kind: fragmentKind,
201
216
  path: value.path,
202
217
  mode: value.mode,
203
- ...(value.type === "cron" ? { name: value.name } : {}),
218
+ ...(value.type === "cron"
219
+ ? { name: value.name }
220
+ : { nativeName: readNativeSkillName(value.content) }),
204
221
  content: value.content,
205
222
  sha256: sha256(bytes),
206
223
  });
@@ -282,6 +299,11 @@ export function buildDefaultProfileBundle({
282
299
  new Set(files.map((file) => file.path)).size !== files.length ||
283
300
  new Set(files.filter((file) => file.type === "skill").map((file) => file.id))
284
301
  .size !== files.filter((file) => file.type === "skill").length ||
302
+ new Set(
303
+ files
304
+ .filter((file) => file.type === "skill")
305
+ .map((file) => file.nativeName)
306
+ ).size !== files.filter((file) => file.type === "skill").length ||
285
307
  new Set(files.filter((file) => file.type === "cron").map((file) => file.name))
286
308
  .size !== files.filter((file) => file.type === "cron").length
287
309
  ) {
@@ -359,6 +359,7 @@ function readBundle(bundleRoot) {
359
359
  entry.mode !== "0444" ||
360
360
  entry.path !== expectedPath ||
361
361
  !SHA256.test(entry.sha256 ?? "") ||
362
+ (entry.type === "skill" && !MANAGED_ID.test(entry.nativeName ?? "")) ||
362
363
  (entry.type === "cron" &&
363
364
  (!MANAGED_ID.test(entry.name ?? "") ||
364
365
  !entry.name.startsWith("sellable-default-")))
@@ -588,7 +589,12 @@ export async function reconcileDefaultProfileBundle({
588
589
  if (sha256(readRegular(plan.path, 64 * 1024)) !== entry.sha256)
589
590
  throw new Error("default_profile_skill_readback_rejected");
590
591
  }
591
- actions.push({ type: "skill", id: entry.id, status: plan.status });
592
+ actions.push({
593
+ type: "skill",
594
+ id: entry.id,
595
+ nativeName: entry.nativeName,
596
+ status: plan.status,
597
+ });
592
598
  receiptEntries.push({
593
599
  type: "skill",
594
600
  id: entry.id,
@@ -43,7 +43,7 @@ ARG STRIPE_CLI_PACKAGE=@stripe/cli-linux-x64@1.45.0
43
43
  ARG STRIPE_CLI_INTEGRITY=sha512-1ZhoPpoweYfynqsvhCLlTjZ7lPz5IKtxqAMT5MBy6zrwLRTP9x0T6r8h/jLYL8lRH1c7zC/6X6/XUu2V+r9Bog==
44
44
  ARG DEFAULT_PROFILE_BUNDLE_FIXTURE_VERSION=1
45
45
  ARG DEFAULT_PROFILE_BUNDLE_VERSION=3
46
- ARG DEFAULT_PROFILE_BUNDLE_DIGEST=8030143cc1a10928564511f24d44643bd697d573332324c5d9a7a32d4fdbaf85
46
+ ARG DEFAULT_PROFILE_BUNDLE_DIGEST=197fb4ed5a60cd1a3a06a46aa1fc53a04bb1e6c1f872e96a0ce2cc28bf2856de
47
47
 
48
48
  COPY --from=slack-pp-cli-builder --chmod=0555 /out/slack-pp-cli /usr/local/bin/slack-pp-cli
49
49
 
@@ -21,7 +21,7 @@ ARG PLAYWRIGHT_BROWSER_REVISION=1234
21
21
  ARG TIRITH_ARCHIVE_SHA256=6cdbe35e8f9ccf42e70ad95b501c93cd218ac18201c3df958d54f6ba0d995ce2
22
22
  ARG DEFAULT_PROFILE_BUNDLE_FIXTURE_VERSION=1
23
23
  ARG DEFAULT_PROFILE_BUNDLE_VERSION=3
24
- ARG DEFAULT_PROFILE_BUNDLE_DIGEST=7e8e6ff740f11aaaa3d6da2e9f067a66866d259ac4233036ff691dae973ce5f3
24
+ ARG DEFAULT_PROFILE_BUNDLE_DIGEST=301ed49582dbfb29453ff2c2fa26579da6771d19f58e12218c5400db2e14318d
25
25
 
26
26
  RUN --mount=type=secret,id=mcp_trust_root,required=true \
27
27
  test -s /run/secrets/mcp_trust_root \
@@ -1041,7 +1041,7 @@ export function executeExternalSkillsBridgeOperation(
1041
1041
 
1042
1042
  /**
1043
1043
  * @param {{
1044
- * actions?: Array<{type: string, id: string}>,
1044
+ * actions?: Array<{type: string, id: string, nativeName?: string}>,
1045
1045
  * profileId?: string,
1046
1046
  * dataRoot?: string,
1047
1047
  * bridge?: typeof executeExternalSkillsBridgeOperation,
@@ -1062,17 +1062,27 @@ export function proveDefaultProfileNativeSkills({
1062
1062
  callerProfileId: profileId,
1063
1063
  ...(nativeCallTimeoutMs === undefined ? {} : { nativeCallTimeoutMs }),
1064
1064
  };
1065
+ for (const action of managed) {
1066
+ if (!SAFE_NAME.test(action.nativeName ?? ""))
1067
+ fail("default_profile_native_skill_name_missing");
1068
+ }
1065
1069
  const inventory = bridge({ operation: "list" }, options);
1066
1070
  const proofs = managed.map((action) => {
1067
- const skill = inventory.skills.find((entry) => entry.name === action.id);
1071
+ const skill = inventory.skills.find(
1072
+ (entry) => entry.name === action.nativeName
1073
+ );
1068
1074
  if (!skill) fail("default_profile_native_skill_missing");
1069
1075
  const viewed = bridge(
1070
1076
  { operation: "read", skillId: skill.skillId },
1071
1077
  options
1072
1078
  );
1073
- if (!viewed.ok || viewed.skill?.name !== action.id)
1079
+ if (!viewed.ok || viewed.skill?.name !== action.nativeName)
1074
1080
  fail("default_profile_native_skill_readback_rejected");
1075
- return { id: action.id, fileSha256: viewed.fileSha256 };
1081
+ return {
1082
+ id: action.id,
1083
+ nativeName: action.nativeName,
1084
+ fileSha256: viewed.fileSha256,
1085
+ };
1076
1086
  });
1077
1087
  return { status: "PROVEN", digest: sha256(stableJson(proofs)) };
1078
1088
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sellable/install",
3
- "version": "0.1.751",
3
+ "version": "0.1.752",
4
4
  "type": "module",
5
5
  "description": "One-command installer for Sellable MCP in Claude Code, Codex, and Hermes",
6
6
  "bin": {