@trillboards/cli 0.1.1 → 0.1.3

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.
@@ -1,9 +1,9 @@
1
1
  import { BaseCommand } from '../../base-command.js';
2
- export default class Getdeviceheartbeat extends BaseCommand {
2
+ export default class Csivenueoccupancy extends BaseCommand {
3
3
  static description: string;
4
4
  static examples: string[];
5
5
  static args: {
6
- deviceId: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
6
+ screenId: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
7
7
  };
8
8
  static flags: {
9
9
  'api-key': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
@@ -1,26 +1,26 @@
1
- // AUTO-GENERATED from OpenAPI spec (device-api) -- do not edit manually
1
+ // AUTO-GENERATED from OpenAPI spec (sdk-api) -- do not edit manually
2
2
  // Regenerate with: npm run generate
3
3
  import { Args } from '@oclif/core';
4
4
  import { BaseCommand } from '../../base-command.js';
5
5
  import { apiRequest } from '../../http.js';
6
6
  import { formatOutput } from '../../output.js';
7
- export default class Getdeviceheartbeat extends BaseCommand {
8
- static description = "Read live device heartbeat state.";
9
- static examples = [`$ trillboards generated device-heartbeat get`];
7
+ export default class Csivenueoccupancy extends BaseCommand {
8
+ static description = "Real-time venue occupancy from WiFi CSI sensing.";
9
+ static examples = [`$ trillboards generated csi-venue-occupancy`];
10
10
  static args = {
11
- deviceId: Args.string({ description: 'Device fingerprint or external device ID.', required: true }),
11
+ screenId: Args.string({ description: 'Mongo ObjectId of the screen / venue sensing node (24-char lowercase hex).', required: true }),
12
12
  };
13
13
  static flags = {
14
14
  ...BaseCommand.baseFlags,
15
15
  };
16
16
  async run() {
17
- const { args, flags } = await this.parse(Getdeviceheartbeat);
17
+ const { args, flags } = await this.parse(Csivenueoccupancy);
18
18
  this.setParsedFlags(flags);
19
19
  const apiKey = this.getApiKey();
20
20
  if (!apiKey)
21
21
  this.error('Not logged in. Run: trillboards login');
22
- let urlPath = '/v1/partner/device/{deviceId}/heartbeat';
23
- urlPath = urlPath.replace('{deviceId}', args['deviceId']);
22
+ let urlPath = '/v2/csi/venue/{screenId}/occupancy';
23
+ urlPath = urlPath.replace('{screenId}', args['screenId']);
24
24
  const params = {};
25
25
  const result = await apiRequest('GET', urlPath, {
26
26
  apiKey,
@@ -15,6 +15,37 @@ export declare function colorize(text: string, color: keyof typeof ansi): string
15
15
  * Wrap text in an OSC-8 terminal hyperlink. Supporting terminals render `label` as a
16
16
  * clickable link to `url`; others just show the label (so always print the raw URL too).
17
17
  * OSC-8: ESC ] 8 ; ; <url> BEL <label> ESC ] 8 ; ; BEL
18
+ *
19
+ * ── THIS LINK IS UNTRACKED, AND CPA ATTRIBUTION ON IT IS REFUSED FOR NOW ──
20
+ *
21
+ * Both call sites (`render.ts` "Play sponsored video", `commands/ads/start.ts`)
22
+ * point straight at the destination — no interstitial, no token, no redirect —
23
+ * and `agent-hook.ts` appends `campaignLink` raw. A standing proposal was to turn
24
+ * this into a tracked click into an affiliate network (Impact / PartnerStack) and
25
+ * bill CPA on the conversion, with impressions as upside.
26
+ *
27
+ * The CLICK half is genuinely cheap and is NOT the blocker: the server already
28
+ * mints signed first-party beacons (`services/programmatic/agentDirectBeacon.js`
29
+ * → `attributionSignature.sign`), `event` is already a signed parameter, so a
30
+ * `click` variant is a small addition on a proven rail.
31
+ *
32
+ * The CPA half is what is refused, and it is refused on substrate, not effort:
33
+ * - There is no affiliate relationship. Impact / PartnerStack appear nowhere in
34
+ * `trillboard-api/`, `trillboards-cli/` or `trillboards-ads-sdk/` outside
35
+ * marketing copy — no client, no credentials path, no postback receiver.
36
+ * - There is no conversion ingestion path to land one in.
37
+ * `services/constants/ingestionPaths.js` enumerates `agent_direct`,
38
+ * `owned_direct`, `vast_event`, `proof_of_play`, `partner_sdk`. A conversion
39
+ * is not an impression and must not be smuggled in as one — billing here is
40
+ * impression-only via signed beacons, and `completed_impressions` is the
41
+ * revenue SoR precisely because it counts plays, not outcomes.
42
+ * - A terminal click produces NO callback to this process. The emulator opens
43
+ * the URL; the CLI never learns it happened. So the whole design depends on a
44
+ * server-side redirect that does not exist yet.
45
+ *
46
+ * Building an attestation-based payout rail against a network we have no contract
47
+ * with would mean inventing both the counterparty and the revenue definition. The
48
+ * prerequisite is a signed affiliate agreement, not more code.
18
49
  */
19
50
  export declare function osc8(url: string, label: string): string;
20
51
  /**
@@ -20,6 +20,37 @@ export function colorize(text, color) {
20
20
  * Wrap text in an OSC-8 terminal hyperlink. Supporting terminals render `label` as a
21
21
  * clickable link to `url`; others just show the label (so always print the raw URL too).
22
22
  * OSC-8: ESC ] 8 ; ; <url> BEL <label> ESC ] 8 ; ; BEL
23
+ *
24
+ * ── THIS LINK IS UNTRACKED, AND CPA ATTRIBUTION ON IT IS REFUSED FOR NOW ──
25
+ *
26
+ * Both call sites (`render.ts` "Play sponsored video", `commands/ads/start.ts`)
27
+ * point straight at the destination — no interstitial, no token, no redirect —
28
+ * and `agent-hook.ts` appends `campaignLink` raw. A standing proposal was to turn
29
+ * this into a tracked click into an affiliate network (Impact / PartnerStack) and
30
+ * bill CPA on the conversion, with impressions as upside.
31
+ *
32
+ * The CLICK half is genuinely cheap and is NOT the blocker: the server already
33
+ * mints signed first-party beacons (`services/programmatic/agentDirectBeacon.js`
34
+ * → `attributionSignature.sign`), `event` is already a signed parameter, so a
35
+ * `click` variant is a small addition on a proven rail.
36
+ *
37
+ * The CPA half is what is refused, and it is refused on substrate, not effort:
38
+ * - There is no affiliate relationship. Impact / PartnerStack appear nowhere in
39
+ * `trillboard-api/`, `trillboards-cli/` or `trillboards-ads-sdk/` outside
40
+ * marketing copy — no client, no credentials path, no postback receiver.
41
+ * - There is no conversion ingestion path to land one in.
42
+ * `services/constants/ingestionPaths.js` enumerates `agent_direct`,
43
+ * `owned_direct`, `vast_event`, `proof_of_play`, `partner_sdk`. A conversion
44
+ * is not an impression and must not be smuggled in as one — billing here is
45
+ * impression-only via signed beacons, and `completed_impressions` is the
46
+ * revenue SoR precisely because it counts plays, not outcomes.
47
+ * - A terminal click produces NO callback to this process. The emulator opens
48
+ * the URL; the CLI never learns it happened. So the whole design depends on a
49
+ * server-side redirect that does not exist yet.
50
+ *
51
+ * Building an attestation-based payout rail against a network we have no contract
52
+ * with would mean inventing both the counterparty and the revenue definition. The
53
+ * prerequisite is a signed affiliate agreement, not more code.
23
54
  */
24
55
  export function osc8(url, label) {
25
56
  const ESC = String.fromCharCode(27); // \x1b
@@ -9,6 +9,48 @@
9
9
  *
10
10
  * This is the I/O glue — the decision logic (dead-time, capability, render commands,
11
11
  * fetch) all lives in unit-tested pure modules. Never lets ad logic break the agent.
12
+ *
13
+ * ── REFUSED: rendering the ad INSIDE the agent's own grid ──────────────────────
14
+ *
15
+ * There was a standing proposal to make this wrapper draw the ad in the coding
16
+ * agent's own terminal instead of on a side surface, by same-length byte-patching
17
+ * the agent binary and re-signing it with `codesign`, or by `DYLD_INSERT_LIBRARIES`
18
+ * interposing its write path. Both are technically achievable. Neither is being
19
+ * built, and the reason belongs here rather than in a tracking list, because this
20
+ * `onData` tee is exactly the code it would replace.
21
+ *
22
+ * 1. IT BREAKS THE THING IT INJECTS INTO. Patching a vendor's binary invalidates
23
+ * that vendor's code signature. Re-signing it with OUR certificate makes us the
24
+ * attesting party for someone else's software, and on macOS a re-signed binary
25
+ * loses the notarization and the entitlements the original shipped with. A
26
+ * DYLD interpose is the same trespass at runtime: it puts our code inside a
27
+ * process the user trusts with their source tree and their credentials. An ad
28
+ * surface is not a good enough reason to hold either of those.
29
+ *
30
+ * 2. THE FAIL-OPEN PROMISE CANNOT BE KEPT. Everything else here is safe because
31
+ * it is ADDITIVE — `onData` copies bytes, it never rewrites them, so a bug in
32
+ * ad logic cannot corrupt the agent's display. A compositor that reserves rows
33
+ * inside the agent's grid has to rewrite cursor and scroll-region sequences it
34
+ * does not own, and there is no version of that which degrades to "the agent
35
+ * looks normal". "Behind a flag, fail-open" describes a fallback this design
36
+ * does not have.
37
+ *
38
+ * The refusal rests on 1 and 2, which are properties of the technique itself.
39
+ *
40
+ * RETRACTED — "it would ship to nobody". An earlier version of this note gave a
41
+ * third reason: that `@trillboards/cli` was stuck at 0.1.1 and the whole Leg A
42
+ * surface was unpublished. That is FALSE, and it is recorded here because it is
43
+ * an easy thing to re-derive wrongly from `publish-cli.yml`'s skip-if-published
44
+ * branch. npm's `gitHead` for 0.1.1 is `01696a57`, that commit IS an ancestor of
45
+ * `production`, and there are ZERO commits to `trillboards-cli/` after it — so
46
+ * the published tarball is current and Leg A has been installable since
47
+ * 2026-06-21. Do not repeat the claim, and do not weigh distribution as an
48
+ * argument here at all: it would not save this design if it were true, and it is
49
+ * not true.
50
+ *
51
+ * If this is ever revisited, the prerequisite is a way to render inside another
52
+ * process that does not forge that process's signature and can genuinely fail
53
+ * open — not a better patching technique, and not a distribution milestone.
12
54
  */
13
55
  import type { VirtualScreenCreative } from './ads-client.js';
14
56
  import type { SurfaceCapabilities } from './capability.js';
@@ -9,6 +9,48 @@
9
9
  *
10
10
  * This is the I/O glue — the decision logic (dead-time, capability, render commands,
11
11
  * fetch) all lives in unit-tested pure modules. Never lets ad logic break the agent.
12
+ *
13
+ * ── REFUSED: rendering the ad INSIDE the agent's own grid ──────────────────────
14
+ *
15
+ * There was a standing proposal to make this wrapper draw the ad in the coding
16
+ * agent's own terminal instead of on a side surface, by same-length byte-patching
17
+ * the agent binary and re-signing it with `codesign`, or by `DYLD_INSERT_LIBRARIES`
18
+ * interposing its write path. Both are technically achievable. Neither is being
19
+ * built, and the reason belongs here rather than in a tracking list, because this
20
+ * `onData` tee is exactly the code it would replace.
21
+ *
22
+ * 1. IT BREAKS THE THING IT INJECTS INTO. Patching a vendor's binary invalidates
23
+ * that vendor's code signature. Re-signing it with OUR certificate makes us the
24
+ * attesting party for someone else's software, and on macOS a re-signed binary
25
+ * loses the notarization and the entitlements the original shipped with. A
26
+ * DYLD interpose is the same trespass at runtime: it puts our code inside a
27
+ * process the user trusts with their source tree and their credentials. An ad
28
+ * surface is not a good enough reason to hold either of those.
29
+ *
30
+ * 2. THE FAIL-OPEN PROMISE CANNOT BE KEPT. Everything else here is safe because
31
+ * it is ADDITIVE — `onData` copies bytes, it never rewrites them, so a bug in
32
+ * ad logic cannot corrupt the agent's display. A compositor that reserves rows
33
+ * inside the agent's grid has to rewrite cursor and scroll-region sequences it
34
+ * does not own, and there is no version of that which degrades to "the agent
35
+ * looks normal". "Behind a flag, fail-open" describes a fallback this design
36
+ * does not have.
37
+ *
38
+ * The refusal rests on 1 and 2, which are properties of the technique itself.
39
+ *
40
+ * RETRACTED — "it would ship to nobody". An earlier version of this note gave a
41
+ * third reason: that `@trillboards/cli` was stuck at 0.1.1 and the whole Leg A
42
+ * surface was unpublished. That is FALSE, and it is recorded here because it is
43
+ * an easy thing to re-derive wrongly from `publish-cli.yml`'s skip-if-published
44
+ * branch. npm's `gitHead` for 0.1.1 is `01696a57`, that commit IS an ancestor of
45
+ * `production`, and there are ZERO commits to `trillboards-cli/` after it — so
46
+ * the published tarball is current and Leg A has been installable since
47
+ * 2026-06-21. Do not repeat the claim, and do not weigh distribution as an
48
+ * argument here at all: it would not save this design if it were true, and it is
49
+ * not true.
50
+ *
51
+ * If this is ever revisited, the prerequisite is a way to render inside another
52
+ * process that does not forge that process's signature and can genuinely fail
53
+ * open — not a better patching technique, and not a distribution milestone.
12
54
  */
13
55
  import { spawn as childSpawn } from 'node:child_process';
14
56
  import { createRequire } from 'node:module';