@plannotator/pi-extension 0.28.48 → 0.28.49

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.
@@ -21,9 +21,12 @@
21
21
  * address (every entry in 100.64.0.0/10 or fd7a:115c:a1e0::/48, so a local
22
22
  * reverse proxy that passes a client's headers on cannot make a forged
23
23
  * login the owner), and the login is the one that owns this machine
24
- * (`tailscale status --json`, Self.UserID -> LoginName).
24
+ * (`tailscale status --json`, Self.UserID -> LoginName), or, when
25
+ * Tailscale names no owner (a tagged machine, or an untagged one whose
26
+ * owner it does not report), one of the logins in `inboxTailscaleAllow`,
27
+ * the rule the Inbox's `isOwnerRequest` follows.
25
28
  * - `peer`: through serve and anything else (another login, a tagged device
26
- * with no login, a funnel request, or an owner nobody could read).
29
+ * with no login, a funnel request, or no owner named and no allowlist).
27
30
  *
28
31
  * The same marks the Inbox's window port refuses (#1867: a local reverse
29
32
  * proxy that sends only loopback `X-Forwarded-For` reads as local).
@@ -90,9 +93,13 @@ export function cameThroughTailscale(headers: Headers): boolean {
90
93
  return value !== null && value.split(",").map(forwardedAddress).some(isTailnetAddress);
91
94
  }
92
95
 
93
- /** Who a request is from, for a session whose machine is owned by `ownerLogin` (null: nobody could say). */
94
- export function tailnetAudience(headers: Headers, ownerLogin: string | null): TailnetAudience {
96
+ /**
97
+ * Who a request is from, for a session whose owner is any of `ownerLogins`
98
+ * (`readTailnetOwners` in packages/server/session-tailnet.ts: the owner
99
+ * Tailscale names, else the allowlist). Empty: nobody is the owner.
100
+ */
101
+ export function tailnetAudience(headers: Headers, ownerLogins: readonly string[]): TailnetAudience {
95
102
  if (!cameThroughTailscaleServe(headers)) return "local";
96
- if (!ownerLogin || !forwardedForIsTailnet(headers)) return "peer";
97
- return checkTailnetIdentity(headers, [normalizeTailnetLogin(ownerLogin)]).ok ? "owner" : "peer";
103
+ if (ownerLogins.length === 0 || !forwardedForIsTailnet(headers)) return "peer";
104
+ return checkTailnetIdentity(headers, ownerLogins.map(normalizeTailnetLogin)).ok ? "owner" : "peer";
98
105
  }
@@ -0,0 +1,21 @@
1
+ // @generated — DO NOT EDIT. Source: packages/core/ulid.ts
2
+ /**
3
+ * A ULID (48-bit millisecond time + 80 random bits, Crockford base32), so ids
4
+ * sort by creation time and a later sync can keep them as they are. The
5
+ * Inbox's ids (`msg_…`) and Shape's (`shp_…`) use it. No imports: Pi vendors it.
6
+ */
7
+ const CROCKFORD = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
8
+
9
+ export function ulid(now: number = Date.now()): string {
10
+ let time = Math.max(0, Math.floor(now));
11
+ let timePart = "";
12
+ for (let i = 0; i < 10; i++) {
13
+ timePart = CROCKFORD[time % 32] + timePart;
14
+ time = Math.floor(time / 32);
15
+ }
16
+ const bytes = new Uint8Array(16);
17
+ globalThis.crypto.getRandomValues(bytes);
18
+ let randomPart = "";
19
+ for (let i = 0; i < 16; i++) randomPart += CROCKFORD[bytes[i]! % 32];
20
+ return timePart + randomPart;
21
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plannotator/pi-extension",
3
- "version": "0.28.48",
3
+ "version": "0.28.49",
4
4
  "type": "module",
5
5
  "description": "Plannotator Pi extension - interactive plan review with annotations, annotate agent messages, and review code/PRs",
6
6
  "author": "backnotprop",