@camstack/server 1.2.131 → 1.2.132

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.
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ /**
3
+ * well-known-app-links — the two files a Universal/App Link needs the DOMAIN
4
+ * to vouch for.
5
+ *
6
+ * The viewer app already declares `applinks:<domain>` (iOS) and an
7
+ * `autoVerify` intent filter (Android) — what was missing is the other half
8
+ * of the handshake: the domain serving `/.well-known/apple-app-site-association`
9
+ * and `/.well-known/assetlinks.json`. Modelled on the Zentik notifier, which
10
+ * runs this exact pair in production.
11
+ *
12
+ * The AASA scopes the app to the viewer mount only (`/viewer/camstack/*`):
13
+ * the hub root also serves the admin UI and data planes, and a tap on those
14
+ * must stay in the browser.
15
+ *
16
+ * Android's verification additionally needs the signing-cert SHA-256
17
+ * fingerprints, which live in the EAS keystore and cannot be derived here —
18
+ * they arrive via `CAMSTACK_ANDROID_CERT_SHA256` (comma-separated). Empty is
19
+ * ACCEPTED and produces a valid file that fails auto-verification (the OS
20
+ * shows a disambiguation dialog): same trade-off the Zentik file ships with.
21
+ */
22
+ Object.defineProperty(exports, "__esModule", { value: true });
23
+ exports.buildAppLinkFiles = buildAppLinkFiles;
24
+ exports.parseCertFingerprints = parseCertFingerprints;
25
+ /** Apple team + bundle ids, mirrored from the viewer's app.config.ts. */
26
+ const APPLE_TEAM_ID = 'C3F24V5NS5';
27
+ const BUNDLE_ID = 'com.apocaliss92.camstack';
28
+ const BUNDLE_ID_DEV = 'com.apocaliss92.camstack.dev';
29
+ /** The only path family the app claims on this domain. */
30
+ const VIEWER_COMPONENT = '/viewer/camstack/*';
31
+ function buildAppLinkFiles(androidCertSha256) {
32
+ const appIds = [`${APPLE_TEAM_ID}.${BUNDLE_ID}`, `${APPLE_TEAM_ID}.${BUNDLE_ID_DEV}`];
33
+ return {
34
+ appleAppSiteAssociation: {
35
+ applinks: {
36
+ apps: [],
37
+ details: [
38
+ {
39
+ appIDs: appIds,
40
+ components: [{ '/': VIEWER_COMPONENT, comment: 'Viewer deep links' }],
41
+ },
42
+ // Legacy `paths` block for pre-iOS-13 parsers, as Zentik ships.
43
+ { appID: appIds[0], paths: [VIEWER_COMPONENT] },
44
+ ],
45
+ },
46
+ webcredentials: { apps: appIds },
47
+ },
48
+ assetLinks: [BUNDLE_ID, BUNDLE_ID_DEV].map((pkg) => ({
49
+ relation: ['delegate_permission/common.handle_all_urls'],
50
+ target: {
51
+ namespace: 'android_app',
52
+ package_name: pkg,
53
+ sha256_cert_fingerprints: [...androidCertSha256],
54
+ },
55
+ })),
56
+ };
57
+ }
58
+ /** Parse the comma-separated env form; junk and empties dropped. */
59
+ function parseCertFingerprints(raw) {
60
+ if (raw === undefined)
61
+ return [];
62
+ return raw
63
+ .split(',')
64
+ .map((s) => s.trim().toUpperCase())
65
+ .filter((s) => /^[0-9A-F]{2}(:[0-9A-F]{2}){31}$/.test(s));
66
+ }
package/dist/main.js CHANGED
@@ -75,6 +75,7 @@ const boot_config_1 = require("./boot/boot-config");
75
75
  const integration_id_backfill_1 = require("./boot/integration-id-backfill");
76
76
  const post_boot_service_1 = require("./boot/post-boot.service");
77
77
  const addon_package_service_1 = require("./core/addon/addon-package.service");
78
+ const well_known_app_links_1 = require("./core/app-links/well-known-app-links");
78
79
  const addon_registry_service_1 = require("./core/addon/addon-registry.service");
79
80
  const addon_bridge_service_1 = require("./core/addon-bridge/addon-bridge.service");
80
81
  const addon_pages_service_1 = require("./core/addon-pages/addon-pages.service");
@@ -1127,6 +1128,18 @@ async function bootstrap() {
1127
1128
  // Register UI routes before Fastify starts, but resolve their forked
1128
1129
  // providers after listen. During a cold boot the control plane is therefore
1129
1130
  // immediately reachable while the non-critical UI runners finish starting.
1131
+ // Universal/App Link handshake: the domain's half of the pair the viewer
1132
+ // app already declares (applinks entitlement + autoVerify intent filter).
1133
+ // Unauthenticated by design — Apple's CDN and Android's verifier fetch these
1134
+ // with no cookies; content-type must be application/json and no redirect.
1135
+ {
1136
+ const { appleAppSiteAssociation, assetLinks } = (0, well_known_app_links_1.buildAppLinkFiles)((0, well_known_app_links_1.parseCertFingerprints)(process.env['CAMSTACK_ANDROID_CERT_SHA256']));
1137
+ const aasa = JSON.stringify(appleAppSiteAssociation);
1138
+ const assetlinks = JSON.stringify(assetLinks);
1139
+ fastify.get('/.well-known/apple-app-site-association', async (_request, reply) => reply.type('application/json').send(aasa));
1140
+ fastify.get('/apple-app-site-association', async (_request, reply) => reply.type('application/json').send(aasa));
1141
+ fastify.get('/.well-known/assetlinks.json', async (_request, reply) => reply.type('application/json').send(assetlinks));
1142
+ }
1130
1143
  fastify.get('/viewer', async (_request, reply) => reply.redirect(`${VIEWER_MOUNT}/`));
1131
1144
  fastify.get('/viewer/', async (_request, reply) => reply.redirect(`${VIEWER_MOUNT}/`));
1132
1145
  fastify.get('/webrtc-test.html', async (_request, reply) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/server",
3
- "version": "1.2.131",
3
+ "version": "1.2.132",
4
4
  "private": false,
5
5
  "files": [
6
6
  "dist",
@@ -33,14 +33,14 @@
33
33
  ]
34
34
  },
35
35
  "dependencies": {
36
- "@camstack/addon-admin-ui": "1.2.79",
36
+ "@camstack/addon-admin-ui": "1.2.80",
37
37
  "@camstack/addon-agent-ui": "1.2.22",
38
38
  "@camstack/addon-auth": "1.2.24",
39
39
  "@camstack/addon-decoder-nodeav": "1.2.21",
40
40
  "@camstack/addon-notifiers": "1.2.26",
41
41
  "@camstack/addon-pipeline": "1.2.96",
42
- "@camstack/addon-pipeline-orchestrator": "1.2.79",
43
- "@camstack/addon-post-analysis": "1.2.94",
42
+ "@camstack/addon-pipeline-orchestrator": "1.2.80",
43
+ "@camstack/addon-post-analysis": "1.2.95",
44
44
  "@camstack/sdk": "1.2.24",
45
45
  "@camstack/shm-ring": "1.1.21",
46
46
  "@camstack/system": "1.2.105",