appduct 0.9.0 → 0.10.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/README.md CHANGED
@@ -22,7 +22,7 @@ appduct link --scheme myapp --qr
22
22
 
23
23
  `link` needs your app's deep-link scheme: pass `--scheme` (the app's `expo.scheme`, or its bare-RN equivalent), or set `"scheme"` once in `~/.appduct/config.json` and omit the flag. Without either, the command exits with a usage error.
24
24
 
25
- Scan the QR (or open the deep link) in a Appduct-enabled app, then:
25
+ Scan the QR (or open the deep link) in an Appduct-enabled app, then:
26
26
 
27
27
  ```bash
28
28
  appduct tools
@@ -31,7 +31,7 @@
31
31
  * future stub could ship them) without the real implementation being present, exactly the reason
32
32
  * the Android signals below aren't all treated as equally authoritative either.
33
33
  * - Android: the primary signal is `AppductNativeMarker`
34
- * (`packages/native/android/core/src/main/java/com/callstackincubator/appduct/AppductNativeMarker.kt`,
34
+ * (`packages/native/android/core/src/main/java/com/callstack/appduct/AppductNativeMarker.kt`,
35
35
  * vendored into `@appduct/react-native` at `android/core/src/main/java/...`), a marker class with no
36
36
  * other purpose. Its fully-qualified name is kept unminified and unremoved by a `-keep` rule in
37
37
  * `consumer-rules.pro` (same vendoring path), shipped to every consuming app via `consumerProguardFiles`
@@ -41,10 +41,12 @@
41
41
  * minification in every supported consumer setup.
42
42
  *
43
43
  * Two more signals are kept as fallbacks for artifacts built before this marker existed: the
44
- * `com.callstackincubator.appduct` package string in the dex string pool (survives as long as
44
+ * `com.callstack.appduct` package string in the dex string pool (and its pre-rename spelling,
45
+ * `com.callstackincubator.appduct` — every Android marker below is matched against both, so an
46
+ * app built against Appduct 0.9.0 or earlier is still detected) (survives as long as
45
47
  * R8/ProGuard minification+obfuscation isn't applied to it — an aggressive release config with no keep
46
48
  * rule for this package can rename it away) and the plugin-authored meta-data key names in
47
- * `AndroidManifest.xml` (`com.callstackincubator.appduct.CLI_PINS`/`TRUST`/`ALLOW_PRIVATE_LAN_ONLY`):
49
+ * `AndroidManifest.xml` (`com.callstack.appduct.CLI_PINS`/`TRUST`/`ALLOW_PRIVATE_LAN_ONLY`):
48
50
  * those are XML attribute string values written by the config plugin at prebuild time, not compiled
49
51
  * identifiers, so R8 never touches them, but they only exist at all if the config plugin ran. Both
50
52
  * encodings AAPT2 can choose for the manifest string pool (UTF-8 or UTF-16LE) are checked.
@@ -1 +1 @@
1
- {"version":3,"file":"artifact-inspect.d.ts","sourceRoot":"","sources":["../src/artifact-inspect.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4EG;AAQH,MAAM,MAAM,gBAAgB,GAAG,KAAK,GAAG,SAAS,CAAC;AACjD,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC;AAE3D,MAAM,MAAM,eAAe,GACvB,wBAAwB,GACxB,uBAAuB,GACvB,qBAAqB,GACrB,0BAA0B,GAC1B,4BAA4B,GAC5B,iCAAiC,CAAC;AAEtC,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,MAAM,EAAE,cAAc,CAAC;IACvB,OAAO,EAAE,OAAO,CAAC;IACjB;;mCAE+B;IAC/B,OAAO,EAAE,eAAe,EAAE,CAAC;CAC5B,CAAC;AAkCF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF;;YAEY;AACZ,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,gBAAgB,CAAC,CAAC;AAE1F;;4EAE4E;AAC5E,eAAO,MAAM,iBAAiB,EAAE,YAgB/B,CAAC;AA8NF,MAAM,MAAM,sBAAsB,GAAG;IACnC,IAAI,CAAC,EAAE,YAAY,CAAC;CACrB,CAAC;AAEF;;;mEAGmE;AACnE,eAAO,MAAM,eAAe,GAC1B,cAAc,MAAM,EACpB,UAAS,sBAA2B,KACnC,OAAO,CAAC,kBAAkB,CA+C5B,CAAC"}
1
+ {"version":3,"file":"artifact-inspect.d.ts","sourceRoot":"","sources":["../src/artifact-inspect.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8EG;AAQH,MAAM,MAAM,gBAAgB,GAAG,KAAK,GAAG,SAAS,CAAC;AACjD,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC;AAE3D,MAAM,MAAM,eAAe,GACvB,wBAAwB,GACxB,uBAAuB,GACvB,qBAAqB,GACrB,0BAA0B,GAC1B,4BAA4B,GAC5B,iCAAiC,CAAC;AAEtC,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,MAAM,EAAE,cAAc,CAAC;IACvB,OAAO,EAAE,OAAO,CAAC;IACjB;;mCAE+B;IAC/B,OAAO,EAAE,eAAe,EAAE,CAAC;CAC5B,CAAC;AAoDF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF;;YAEY;AACZ,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,gBAAgB,CAAC,CAAC;AAE1F;;4EAE4E;AAC5E,eAAO,MAAM,iBAAiB,EAAE,YAgB/B,CAAC;AAiOF,MAAM,MAAM,sBAAsB,GAAG;IACnC,IAAI,CAAC,EAAE,YAAY,CAAC;CACrB,CAAC;AAEF;;;mEAGmE;AACnE,eAAO,MAAM,eAAe,GAC1B,cAAc,MAAM,EACpB,UAAS,sBAA2B,KACnC,OAAO,CAAC,kBAAkB,CA+C5B,CAAC"}
@@ -31,7 +31,7 @@
31
31
  * future stub could ship them) without the real implementation being present, exactly the reason
32
32
  * the Android signals below aren't all treated as equally authoritative either.
33
33
  * - Android: the primary signal is `AppductNativeMarker`
34
- * (`packages/native/android/core/src/main/java/com/callstackincubator/appduct/AppductNativeMarker.kt`,
34
+ * (`packages/native/android/core/src/main/java/com/callstack/appduct/AppductNativeMarker.kt`,
35
35
  * vendored into `@appduct/react-native` at `android/core/src/main/java/...`), a marker class with no
36
36
  * other purpose. Its fully-qualified name is kept unminified and unremoved by a `-keep` rule in
37
37
  * `consumer-rules.pro` (same vendoring path), shipped to every consuming app via `consumerProguardFiles`
@@ -41,10 +41,12 @@
41
41
  * minification in every supported consumer setup.
42
42
  *
43
43
  * Two more signals are kept as fallbacks for artifacts built before this marker existed: the
44
- * `com.callstackincubator.appduct` package string in the dex string pool (survives as long as
44
+ * `com.callstack.appduct` package string in the dex string pool (and its pre-rename spelling,
45
+ * `com.callstackincubator.appduct` — every Android marker below is matched against both, so an
46
+ * app built against Appduct 0.9.0 or earlier is still detected) (survives as long as
45
47
  * R8/ProGuard minification+obfuscation isn't applied to it — an aggressive release config with no keep
46
48
  * rule for this package can rename it away) and the plugin-authored meta-data key names in
47
- * `AndroidManifest.xml` (`com.callstackincubator.appduct.CLI_PINS`/`TRUST`/`ALLOW_PRIVATE_LAN_ONLY`):
49
+ * `AndroidManifest.xml` (`com.callstack.appduct.CLI_PINS`/`TRUST`/`ALLOW_PRIVATE_LAN_ONLY`):
48
50
  * those are XML attribute string values written by the config plugin at prebuild time, not compiled
49
51
  * identifiers, so R8 never touches them, but they only exist at all if the config plugin ran. Both
50
52
  * encodings AAPT2 can choose for the manifest string pool (UTF-8 or UTF-16LE) are checked.
@@ -87,15 +89,33 @@ const IOS_CORE_MARKER = "AppductCoreMarker";
87
89
  const IOS_OBJC_CLASS_MARKER = "RCTNativeAppduct";
88
90
  const IOS_INFO_PLIST_KEY_MARKERS = ["AppductCliPins", "AppductTrust", "AppductAllowPrivateLanOnly"];
89
91
  // Fully-qualified name of `AppductNativeMarker`
90
- // (packages/native/android/core/src/main/java/com/callstackincubator/appduct/AppductNativeMarker.kt,
91
- // vendored into packages/react-native/android/core/src/main/java/com/callstackincubator/appduct/AppductNativeMarker.kt
92
+ // (packages/native/android/core/src/main/java/com/callstack/appduct/AppductNativeMarker.kt,
93
+ // vendored into packages/react-native/android/core/src/main/java/com/callstack/appduct/AppductNativeMarker.kt
92
94
  // by scripts/sync-native-core.mjs), kept unminified by packages/native/android/core/consumer-rules.pro
93
95
  // (vendored to packages/react-native/android/core/consumer-rules.pro the same way). Checked as a dex
94
96
  // type descriptor (`Lcom/.../AppductNativeMarker;`) — see detectAndroidSignals — which is how the
95
97
  // class's fully-qualified name is actually encoded in classes.dex.
96
- const ANDROID_KEEP_RULE_MARKER_CLASS = "com/callstackincubator/appduct/AppductNativeMarker";
97
- const ANDROID_DEX_PACKAGE_MARKERS = ["com/callstackincubator/appduct", "com.callstackincubator.appduct"];
98
- const ANDROID_MANIFEST_KEY_MARKER = "com.callstackincubator.appduct.";
98
+ //
99
+ // Each of the three Android markers is matched against BOTH the current `com.callstack.*` namespace
100
+ // and the legacy `com.callstackincubator.*` one that every release up to and including 0.9.0
101
+ // shipped. `doctor` inspects artifacts it did not build -- including an app built against an older
102
+ // Appduct, which is exactly the case a release gate runs into -- and reporting `absent` for an app
103
+ // that genuinely bundles Appduct is the one failure mode this tool must never have: it would
104
+ // rubber-stamp shipping Appduct to production. docs/CI.md states the rule ("a broken check must
105
+ // fail loudly, not rubber-stamp a release"); the cost of honouring it here is one extra buffer
106
+ // scan per signal. The legacy entries are load-bearing and must not be dropped while any artifact
107
+ // built before the rename can still be inspected.
108
+ const ANDROID_KEEP_RULE_MARKER_CLASSES = [
109
+ "com/callstack/appduct/AppductNativeMarker",
110
+ "com/callstackincubator/appduct/AppductNativeMarker",
111
+ ];
112
+ const ANDROID_DEX_PACKAGE_MARKERS = [
113
+ "com/callstack/appduct",
114
+ "com.callstack.appduct",
115
+ "com/callstackincubator/appduct",
116
+ "com.callstackincubator.appduct",
117
+ ];
118
+ const ANDROID_MANIFEST_KEY_MARKERS = ["com.callstack.appduct.", "com.callstackincubator.appduct."];
99
119
  const bufferIncludesAscii = (haystack, needle) => {
100
120
  return haystack.includes(Buffer.from(needle, "utf8"));
101
121
  };
@@ -257,14 +277,13 @@ const detectAndroidSignals = (bytes) => {
257
277
  // in every supported consumer setup (see the file-level doc comment). Matched as a dex type
258
278
  // descriptor (`L` + fully-qualified-name-with-slashes + `;`) since that's the actual encoding of
259
279
  // a class name inside classes.dex, not just a loose substring check.
260
- if (bufferIncludesAscii(bytes, `L${ANDROID_KEEP_RULE_MARKER_CLASS};`)) {
280
+ if (ANDROID_KEEP_RULE_MARKER_CLASSES.some((klass) => bufferIncludesAscii(bytes, `L${klass};`))) {
261
281
  signals.push("android-keep-rule-marker");
262
282
  }
263
283
  if (ANDROID_DEX_PACKAGE_MARKERS.some((marker) => bufferIncludesAscii(bytes, marker))) {
264
284
  signals.push("android-dex-package-symbol");
265
285
  }
266
- if (bufferIncludesAscii(bytes, ANDROID_MANIFEST_KEY_MARKER) ||
267
- bufferIncludesUtf16le(bytes, ANDROID_MANIFEST_KEY_MARKER)) {
286
+ if (ANDROID_MANIFEST_KEY_MARKERS.some((marker) => bufferIncludesAscii(bytes, marker) || bufferIncludesUtf16le(bytes, marker))) {
268
287
  signals.push("android-manifest-meta-data-keys");
269
288
  }
270
289
  return signals;
@@ -14,7 +14,7 @@ export const createCli = () => {
14
14
  "an ambient value into a committed file.")
15
15
  .option("--force", "Replace the scheme already recorded in the project config.");
16
16
  cli
17
- .command("keygen", "Generate a Appduct host private key and print its app fingerprint.")
17
+ .command("keygen", "Generate an Appduct host private key and print its app fingerprint.")
18
18
  .option("--out <path>", "Destination path (default: <state-dir>/key.pem).")
19
19
  .option("--force", "Overwrite an existing key at the destination path.");
20
20
  cli
@@ -41,7 +41,7 @@ const QR_INSTRUCTIONS = "This link was NOT delivered to a device — a human has
41
41
  "gives no output while it waits, so calling it before you have asked will look like a hang.";
42
42
  export const CONNECT_TOOL_DESCRIPTOR = {
43
43
  name: CONNECT_TOOL_NAME,
44
- description: "Mint a Appduct session link and get it onto a device. With no \"target\", auto-detects a " +
44
+ description: "Mint an Appduct session link and get it onto a device. With no \"target\", auto-detects a " +
45
45
  "booted iOS simulator or attached Android device and delivers the link to it, returning " +
46
46
  "{ sessionId, delivered: true, autoDetected: true } — this is the normal agent path and needs " +
47
47
  "no human. Pass target \"android\" or \"ios-sim\" (optionally with \"device\") to choose " +
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "appduct",
3
- "version": "0.9.0",
3
+ "version": "0.10.0",
4
4
  "description": "Driving React Native tools without in-app debug UI.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -45,7 +45,7 @@
45
45
  "reflect-metadata": "^0.2.2",
46
46
  "toqr": "^0.1.1",
47
47
  "ws": "^8.18.3",
48
- "@appduct/shared": "0.9.0"
48
+ "@appduct/shared": "0.10.0"
49
49
  },
50
50
  "devDependencies": {
51
51
  "@types/node": "^22.10.0",