querysub 0.489.0 → 0.490.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.
Files changed (40) hide show
  1. package/.claude/settings.local.json +4 -1
  2. package/package.json +2 -1
  3. package/src/-b-authorities/dnsAuthority.ts +80 -42
  4. package/src/-c-identity/IdentityController.ts +13 -12
  5. package/src/-d-trust/NetworkTrust2.ts +6 -6
  6. package/src/-e-certs/EdgeCertController.ts +4 -4
  7. package/src/-e-certs/certAuthority.ts +1 -1
  8. package/src/-f-node-discovery/NodeDiscovery.ts +10 -10
  9. package/src/-g-core-values/NodeCapabilities.ts +4 -3
  10. package/src/-h-path-value-serialize/PathValueSerializer.ts +4 -3
  11. package/src/0-path-value-core/PathValueCommitter.ts +5 -4
  12. package/src/0-path-value-core/PathValueController.ts +4 -4
  13. package/src/0-path-value-core/archiveLocks/ArchiveLocks2.ts +3 -3
  14. package/src/0-path-value-core/pathValueArchives.ts +4 -4
  15. package/src/0-path-value-core/pathValueCore.ts +2 -0
  16. package/src/1-path-client/pathValueClientWatcher.ts +3 -3
  17. package/src/2-proxy/PathValueProxyWatcher.ts +1 -1
  18. package/src/3-path-functions/PathFunctionHelpers.ts +2 -2
  19. package/src/3-path-functions/PathFunctionRunnerMain.ts +1 -1
  20. package/src/3-path-functions/tests/rejectTest.ts +3 -2
  21. package/src/4-deploy/deployGetFunctionsInner.ts +2 -2
  22. package/src/4-deploy/edgeNodes.ts +3 -3
  23. package/src/4-querysub/Querysub.ts +14 -10
  24. package/src/4-querysub/querysubPrediction.ts +0 -11
  25. package/src/deployManager/components/ServiceDetailPage.tsx +1 -1
  26. package/src/deployManager/machineApplyMainCode.ts +4 -4
  27. package/src/deployManager/machineSchema.ts +1 -1
  28. package/src/diagnostics/MachineThreadInfo.tsx +3 -2
  29. package/src/diagnostics/NodeViewer.tsx +7 -1
  30. package/src/diagnostics/logs/IndexedLogs/IndexedLogs.ts +2 -2
  31. package/src/diagnostics/logs/IndexedLogs/MCPIndexedLogs.ts +3 -2
  32. package/src/diagnostics/logs/diskLogGlobalContext.ts +4 -3
  33. package/src/diagnostics/misc-pages/DNSPage.tsx +16 -6
  34. package/src/diagnostics/pathAuditer.ts +4 -4
  35. package/src/diagnostics/watchdog.ts +1 -1
  36. package/src/server.ts +1 -1
  37. package/src/user-implementation/UserPage.tsx +4 -3
  38. package/test.ts +8 -50
  39. package/testEntry2.ts +1 -1
  40. package/src/-a-auth/certs.ts +0 -541
@@ -25,7 +25,10 @@
25
25
  "mcp__node-debugger__removeBreakpoint",
26
26
  "mcp__hottest__runTest",
27
27
  "Bash(yarn test *)",
28
- "Bash(yarn ssh-a-claude *)"
28
+ "Bash(yarn ssh-a-claude *)",
29
+ "WebSearch",
30
+ "WebFetch(domain:blog.cloudflare.com)",
31
+ "WebFetch(domain:developers.cloudflare.com)"
29
32
  ]
30
33
  }
31
34
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "querysub",
3
- "version": "0.489.0",
3
+ "version": "0.490.0",
4
4
  "main": "index.js",
5
5
  "license": "MIT",
6
6
  "note1": "note on node-forge fork, see https://github.com/digitalbazaar/forge/issues/744 for details",
@@ -67,6 +67,7 @@
67
67
  "node-forge": "https://github.com/sliftist/forge#e618181b469b07bdc70b968b0391beb8ef5fecd6",
68
68
  "pako": "^2.1.0",
69
69
  "peggy": "^5.0.6",
70
+ "sliftutils": "^1.5.6",
70
71
  "socket-function": "^1.1.43",
71
72
  "terser": "^5.31.0",
72
73
  "typesafecss": "^0.29.0",
@@ -19,6 +19,26 @@ const DNS_TTLSeconds = {
19
19
 
20
20
  const DNS_REFRESH_STALE_AFTER = timeInDay;
21
21
 
22
+ // We stamp our own "last asserted" time into the record's comment, because Cloudflare's
23
+ // modified_on can only be moved by an actual content change - and re-asserting an already
24
+ // correct record has no content change to make (a create errors with 81058, a no-op edit
25
+ // doesn't bump the timestamp). Reading freshness from text we control sidesteps that entirely,
26
+ // and lets us refresh a stale-but-correct record in place instead of deleting and recreating it.
27
+ const FRESHNESS_REGEX = /<set on:[^>]*>/;
28
+
29
+ /** Strips any prior freshness tag and appends a new one, preserving other comment text. */
30
+ function stampFreshness(comment?: string): string {
31
+ let base = (comment ?? "").replace(FRESHNESS_REGEX, "").trim();
32
+ let stamp = `<set on: ${new Date().toString()}>`;
33
+ return base ? `${base} ${stamp}` : stamp;
34
+ }
35
+ /** Parses our tag back out; 0 (i.e. always stale) when it's absent or unparseable. */
36
+ export function freshnessTime(comment?: string): number {
37
+ let match = FRESHNESS_REGEX.exec(comment ?? "");
38
+ if (!match) return 0;
39
+ return new Date(match[0].replace("<set on:", "").replace(">", "").trim()).getTime() || 0;
40
+ }
41
+
22
42
  export const hasDNSWritePermissions = lazy(async () => {
23
43
  if (!isNode()) return false;
24
44
  if (isClient()) return false;
@@ -56,8 +76,34 @@ export async function getRecordsRaw(type: string, key: string) {
56
76
  content: string;
57
77
  proxied: boolean;
58
78
  modified_on: string;
79
+ // Omitted by Cloudflare when the record has no comment.
80
+ comment?: string;
59
81
  }[]>(`/zones/${zoneId}/dns_records`);
60
- return results.filter(x => x.type === type && x.name === key);
82
+ // DNS names are case-insensitive and Cloudflare returns them lowercased, so a mixed-case key
83
+ // (e.g. a machine id subdomain) would never match an exact-case compare - match lowercased.
84
+ let keyLower = key.toLowerCase();
85
+ return results.filter(x => x.type === type && x.name.toLowerCase() === keyLower);
86
+ }
87
+
88
+ /** Cloudflare's batch endpoint applies deletes, then patches, then posts in a single database
89
+ * transaction. We route edits (patches) through here because the standalone PATCH/PUT verbs
90
+ * aren't usable in our setup, and because it lets "remove others + assert target" happen
91
+ * without a window where the name resolves to nothing. */
92
+ export async function batchRecords(zoneId: string, batch: {
93
+ deletes?: { id: string }[];
94
+ patches?: { id: string; comment?: string }[];
95
+ posts?: { type: string; name: string; content: string; ttl: number; proxied: boolean; comment?: string }[];
96
+ }) {
97
+ let payload: { [key: string]: unknown } = {};
98
+ if (batch.deletes && batch.deletes.length > 0) payload.deletes = batch.deletes;
99
+ if (batch.patches && batch.patches.length > 0) payload.patches = batch.patches;
100
+ if (batch.posts && batch.posts.length > 0) payload.posts = batch.posts;
101
+ try {
102
+ await cloudflarePOSTCall(`/zones/${zoneId}/dns_records/batch`, payload);
103
+ } catch (error) {
104
+ console.error(`Error updating DNS records:`, { error: error, batch });
105
+ throw new Error(`Error updating DNS records. ${JSON.stringify(batch)}. Error: ${error}`);
106
+ }
61
107
  }
62
108
  export async function getRecords(type: string, key: string) {
63
109
  if (key.endsWith(".")) key = key.slice(0, -1);
@@ -81,35 +127,30 @@ export async function deleteRecord(type: string, key: string, value: string) {
81
127
  await cloudflareCall(`/zones/${zoneId}/dns_records/${value.id}`, Buffer.from([]), "DELETE");
82
128
  }
83
129
  }
84
- /** Removes all existing records (unless the record is already present) */
85
- export async function setRecord(type: string, key: string, value: string, proxied?: "proxied") {
86
- let stack = new Error();
130
+ /** Removes all existing records (unless the record is already present and fresh) */
131
+ export async function setRecord(type: string, key: string, value: string, proxied?: "proxied", staleAfter = DNS_REFRESH_STALE_AFTER) {
87
132
  if (key.endsWith(".")) key = key.slice(0, -1);
88
133
  let zoneId = await getZoneId(getRootDomain(key));
89
134
  let prevValues = await getRecordsRaw(type, key);
90
- // NOTE: Apparently if we try to update by just changing proxied, cloudflare complains and
91
- // says "an identical record already exists", even though it doesn't, we changed the proxied value...
92
- let alreadyExisted = prevValues.some(x => x.content === value);
93
- if (alreadyExisted && Date.now() - new Date(prevValues.find(x => x.content === value)!.modified_on).getTime() < DNS_REFRESH_STALE_AFTER) return;
135
+ let existing = prevValues.find(x => x.content === value);
136
+ let others = prevValues.filter(x => x.content !== value);
94
137
 
95
- console.log(magenta(`Removing previous records of ${type} for ${key} ${JSON.stringify(prevValues.map(x => x.content))}`));
96
- let didDeletions = false;
97
- for (let value of prevValues) {
98
- didDeletions = true;
99
- await cloudflareCall(`/zones/${zoneId}/dns_records/${value.id}`, Buffer.from([]), "DELETE");
100
- }
138
+ // Already correct and recently asserted - a prior run also cleaned up the other records,
139
+ // so there is nothing left to do.
140
+ if (existing && Date.now() - freshnessTime(existing.comment) < staleAfter) return;
101
141
 
142
+ // A single atomic batch: drop the wrong records, and either refresh the existing record's
143
+ // comment in place or create it - so the name is never left resolving to nothing.
144
+ let ttl = DNS_TTLSeconds[type as "A"] || 60;
145
+ let comment = stampFreshness(existing?.comment);
102
146
  console.log(magenta(`Setting ${type} record for ${key} to ${value} (previously had ${JSON.stringify(prevValues.map(x => x.content))})`));
103
- const ttl = DNS_TTLSeconds[type as "A"] || 60;
104
- await cloudflarePOSTCall(`/zones/${zoneId}/dns_records`, {
105
- type: type,
106
- name: key,
107
- content: value,
108
- ttl,
109
- proxied: proxied === "proxied",
147
+ await batchRecords(zoneId, {
148
+ deletes: others.map(x => ({ id: x.id })),
149
+ patches: existing ? [{ id: existing.id, comment }] : [],
150
+ posts: existing ? [] : [{ type, name: key, content: value, ttl, proxied: proxied === "proxied", comment }],
110
151
  });
111
- if (!alreadyExisted) {
112
- // NOTE: Apparently... even if the record didn't exist, we still have to wait...
152
+ // Only a brand new record needs to propagate; an in-place comment refresh doesn't change the answer.
153
+ if (!existing) {
113
154
  console.log(`Waiting ${ttl} seconds for DNS to propagate...`);
114
155
  for (let ttlLeft = ttl; ttlLeft > 0; ttlLeft--) {
115
156
  await delay(1000);
@@ -119,29 +160,26 @@ export async function setRecord(type: string, key: string, value: string, proxie
119
160
  }
120
161
  }
121
162
  /** Keeps existing records */
122
- export async function addRecord(type: string, key: string, value: string, proxied?: "proxied") {
163
+ export async function addRecord(type: string, key: string, value: string, proxied?: "proxied", staleAfter = DNS_REFRESH_STALE_AFTER) {
123
164
  if (key.endsWith(".")) key = key.slice(0, -1);
124
165
  let zoneId = await getZoneId(getRootDomain(key));
125
166
  let prevValues = await getRecordsRaw(type, key);
126
- // NOTE: Apparently if we try to update by just changing proxied, cloudflare complains and
127
- // says "an identical record already exists", even though it doesn't, we changed the proxied value...
128
- let alreadyExisted = prevValues.some(x => x.content === value);
129
- if (alreadyExisted && Date.now() - new Date(prevValues.find(x => x.content === value)!.modified_on).getTime() < DNS_REFRESH_STALE_AFTER) return;
167
+ let existing = prevValues.find(x => x.content === value);
168
+ if (existing && Date.now() - freshnessTime(existing.comment) < staleAfter) return;
169
+
170
+ // Same single-batch flow as setRecord, minus the deletes (we keep sibling records here).
171
+ let ttl = DNS_TTLSeconds[type as "A"] || 60;
172
+ let comment = stampFreshness(existing?.comment);
130
173
  console.log(`Adding ${type} record for ${key} to ${value} (previously had ${JSON.stringify(prevValues.map(x => x.content))})`);
131
- const ttl = DNS_TTLSeconds[type as "A"] || 60;
132
- await cloudflarePOSTCall(`/zones/${zoneId}/dns_records`, {
133
- type: type,
134
- name: key,
135
- content: value,
136
- ttl,
137
- proxied: proxied === "proxied",
174
+ await batchRecords(zoneId, {
175
+ patches: existing ? [{ id: existing.id, comment }] : [],
176
+ posts: existing ? [] : [{ type, name: key, content: value, ttl, proxied: proxied === "proxied", comment }],
138
177
  });
139
- if (!alreadyExisted) {
140
- console.log(`Waiting ${ttl} seconds for DNS to propagate...`);
141
- for (let ttlLeft = ttl; ttlLeft > 0; ttlLeft--) {
142
- await delay(1000);
143
- console.log(`${ttlLeft} seconds left...`);
144
- }
145
- console.log(`Done waiting for DNS to update.`);
178
+ if (existing) return;
179
+ console.log(`Waiting ${ttl} seconds for DNS to propagate...`);
180
+ for (let ttlLeft = ttl; ttlLeft > 0; ttlLeft--) {
181
+ await delay(1000);
182
+ console.log(`${ttlLeft} seconds left...`);
146
183
  }
184
+ console.log(`Done waiting for DNS to update.`);
147
185
  }
@@ -9,7 +9,7 @@ import { SocketFunction } from "socket-function/SocketFunction";
9
9
  import { CallerContext } from "socket-function/SocketFunctionTypes";
10
10
  import { cache, cacheWeak, lazy } from "socket-function/src/caching";
11
11
  import { getClientNodeId, getNodeId, getNodeIdDomain, getNodeIdIP, getNodeIdLocation, isClientNodeId } from "socket-function/src/nodeCache";
12
- import { decodeNodeId, getCommonName, getIdentityCA, getMachineId, getOwnMachineId, getPublicIdentifier, getThreadKeyCert, parseCert, sign, validateCertificate, verify } from "../-a-auth/certs";
12
+ import { decodeNodeId, getCommonName, getIdentityCA, getMachineId, getOwnMachineId, getPublicIdentifier, getThreadKeyCert, parseCert, sign, validateCertificate, verify } from "sliftutils/misc/https/certs";
13
13
  import { getShortNumber } from "socket-function/src/bits";
14
14
  import { measureBlock, measureFnc, measureWrap } from "socket-function/src/profiling/measure";
15
15
  import { timeoutToError } from "../errors";
@@ -21,6 +21,7 @@ import { isNode } from "typesafecss";
21
21
  import { areNodeIdsEqual, getOwnNodeId, getOwnThreadId } from "../-f-node-discovery/NodeDiscovery";
22
22
  import { timeInMinute } from "socket-function/src/misc";
23
23
  import { isClient, isServer } from "../config2";
24
+ import { getDomain } from "../config";
24
25
 
25
26
  // NOTE: This used to be small, but we cache this, so it would mean a node on startup would time out, and then we would refuse to talk to it ever again. So... this can't be small
26
27
  const MAX_CHANGE_IDENTITY_TIMEOUT = timeInMinute * 5;
@@ -81,7 +82,7 @@ export function debugNodeId(nodeId: string) {
81
82
 
82
83
  export function debugNodeThread(nodeId: string) {
83
84
  nodeId = debugNodeId(nodeId);
84
- return decodeNodeId(nodeId)?.threadId || nodeId;
85
+ return decodeNodeId(nodeId, getDomain())?.threadId || nodeId;
85
86
  }
86
87
 
87
88
  /** Gets the nodeId of the machine, which should be consistent. When deciding to trust a node
@@ -91,7 +92,7 @@ export function debugNodeThread(nodeId: string) {
91
92
  export function IdentityController_getMachineId(callerContext: CallerContext, allowEmpty?: "allowEmpty"): string {
92
93
  let location = getNodeIdLocation(callerContext.nodeId);
93
94
  if (location) {
94
- return getMachineId(location.address);
95
+ return getMachineId(location.address, getDomain());
95
96
  }
96
97
  let info = callerInfo.get(callerContext);
97
98
  if (!info) {
@@ -114,7 +115,7 @@ export function IdentityController_getPubKeyShort(callerContext: CallerContext):
114
115
  return info.pubKeyShort;
115
116
  }
116
117
  export const IdentityController_getOwnPubKeyShort = lazy((): number => {
117
- let cert = getThreadKeyCert();
118
+ let cert = getThreadKeyCert(getDomain());
118
119
  let pubKey = getPublicIdentifier(cert.cert);
119
120
  return getShortNumber(pubKey);
120
121
  });
@@ -159,11 +160,11 @@ class IdentityControllerBase {
159
160
  }
160
161
  // If they're calling from the browser, then they're not going to be able to use our machine ID, etc. However, they should be calling an actual https node, so it should still be secure for them.
161
162
  if (payload.clientIsNode) {
162
- let calledMachineId = getMachineId(payload.serverId);
163
- if (calledMachineId !== "127-0-0-1" && calledMachineId !== getOwnMachineId()) {
164
- throw new Error(`Tried to call a different machine. We are ${getOwnMachineId()}, they called ${calledMachineId}`);
163
+ let calledMachineId = getMachineId(payload.serverId, getDomain());
164
+ if (calledMachineId !== "127-0-0-1" && calledMachineId !== getOwnMachineId(getDomain())) {
165
+ throw new Error(`Tried to call a different machine. We are ${getOwnMachineId(getDomain())}, they called ${calledMachineId}`);
165
166
  }
166
- let calledThreadId = decodeNodeId(payload.serverId)?.threadId;
167
+ let calledThreadId = decodeNodeId(payload.serverId, getDomain())?.threadId;
167
168
  if (calledThreadId && calledThreadId !== "127-0-0-1" && calledThreadId !== getOwnThreadId()) {
168
169
  throw new Error(`Tried to call a different thread. We are ${getOwnThreadId()}, they called ${calledThreadId}`);
169
170
  }
@@ -174,7 +175,7 @@ class IdentityControllerBase {
174
175
  verify(payload.cert, signature, payload);
175
176
 
176
177
  // Verify we even trust the issuer/cert pair
177
- validateCertificate(payload.cert, payload.certIssuer);
178
+ validateCertificate(getDomain(), payload.cert, payload.certIssuer);
178
179
 
179
180
  let reconnectNodeId: string | undefined;
180
181
  if (payload.mountedPort) {
@@ -185,7 +186,7 @@ class IdentityControllerBase {
185
186
  }
186
187
 
187
188
  let pubKey = getPublicIdentifier(payload.cert);
188
- let machineId = getMachineId(getCommonName(payload.certIssuer));
189
+ let machineId = getMachineId(getCommonName(payload.certIssuer), getDomain());
189
190
 
190
191
  callerInfo.set(caller, {
191
192
  cert: { certPEM: payload.cert, issuerPEM: payload.certIssuer },
@@ -232,8 +233,8 @@ const IdentityController = SocketFunction.register(
232
233
  // IMPORTANT! We need to cache per connection, not per nodeId, so caching based on connectionId is required!
233
234
  const changeIdentityOnce = cacheWeak(async function changeIdentityOnce(connectionId: { nodeId: string }) {
234
235
  let nodeId = connectionId.nodeId;
235
- let threadKeyCert = getThreadKeyCert();
236
- let issuer = getIdentityCA();
236
+ let threadKeyCert = getThreadKeyCert(getDomain());
237
+ let issuer = getIdentityCA(getDomain());
237
238
  let payload: ChangeIdentityPayload = {
238
239
  time: Date.now(),
239
240
  serverId: nodeId,
@@ -1,5 +1,5 @@
1
1
  import { measureWrap } from "socket-function/src/profiling/measure";
2
- import { getIdentityCA, getMachineId, getOwnMachineId } from "../-a-auth/certs";
2
+ import { getIdentityCA, getMachineId, getOwnMachineId } from "sliftutils/misc/https/certs";
3
3
  import { getArchives } from "../-a-archives/archives";
4
4
  import { isNode, throttleFunction, timeInHour, timeInSecond } from "socket-function/src/misc";
5
5
  import { SocketFunctionHook } from "socket-function/SocketFunctionTypes";
@@ -93,7 +93,7 @@ let populateTrustedCache = lazy(async () => {
93
93
  trustedCache.add(trustedMachineId);
94
94
  }
95
95
  // Always trust ourself
96
- trustedCache.add(getOwnMachineId());
96
+ trustedCache.add(getOwnMachineId(getDomain()));
97
97
 
98
98
  // NOTE: This only happens to servers that we connect to. Also we only allow the machine ID to be this special ID in the case it's on our domain. And because we use HTTPS when connecting to domains, it means that it must be implicitly trusted if it has a certificate for our domain.
99
99
  trustedCache.add("127-0-0-1");
@@ -107,7 +107,7 @@ let populateTrustedCache = lazy(async () => {
107
107
  export async function isNodeTrusted(nodeId: string) {
108
108
  let domainName = getNodeIdDomainMaybeUndefined(nodeId);
109
109
  if (!domainName) return false;
110
- let machineId = getMachineId(domainName);
110
+ let machineId = getMachineId(domainName, getDomain());
111
111
  return await isTrusted(machineId);
112
112
  }
113
113
 
@@ -124,8 +124,8 @@ const loadServerCert = cache(async (machineId: string) => {
124
124
  });
125
125
 
126
126
  export const ensureWeAreTrusted = lazy(measureWrap(async () => {
127
- let machineKeyCert = getIdentityCA();
128
- let machineId = getOwnMachineId();
127
+ let machineKeyCert = getIdentityCA(getDomain());
128
+ let machineId = getOwnMachineId(getDomain());
129
129
  if (!await archives().get(machineId)) {
130
130
  await archives().set(machineId, machineKeyCert.cert);
131
131
  }
@@ -134,7 +134,7 @@ export const ensureWeAreTrusted = lazy(measureWrap(async () => {
134
134
  async function loadTrustCerts(nodeId: string) {
135
135
  let location = getNodeIdLocation(nodeId);
136
136
  if (location) {
137
- let machineId = getMachineId(location.address);
137
+ let machineId = getMachineId(location.address, getDomain());
138
138
  let isTrustedBool = await isTrusted(machineId);
139
139
  if (isTrustedBool) {
140
140
  await loadServerCert(machineId);
@@ -11,7 +11,7 @@
11
11
 
12
12
  import { SocketFunction } from "socket-function/SocketFunction";
13
13
  import { lazy } from "socket-function/src/caching";
14
- import { createX509, generateKeyPair, getMachineId, getOwnMachineId, getThreadKeyCert, parseCert } from "../-a-auth/certs";
14
+ import { createX509, generateKeyPair, getMachineId, getOwnMachineId, getThreadKeyCert, parseCert } from "sliftutils/misc/https/certs";
15
15
  import { backoffRetryLoop, logErrors } from "../errors";
16
16
  import { getHTTPSKeyCert } from "./certAuthority";
17
17
  import { getControllerNodeId } from "../-g-core-values/NodeCapabilities";
@@ -57,8 +57,8 @@ export async function getSNICerts(config: {
57
57
  [getDomain()]: async (callback) => {
58
58
  await EdgeCertController_watchHTTPSKeyCert(callback);
59
59
  },
60
- [getOwnMachineId() + "." + getDomain()]: async (callback) => {
61
- let threadCert = await getThreadKeyCert();
60
+ [getOwnMachineId(getDomain()) + "." + getDomain()]: async (callback) => {
61
+ let threadCert = await getThreadKeyCert(getDomain());
62
62
  callback({
63
63
  key: threadCert.key,
64
64
  cert: threadCert.cert,
@@ -121,7 +121,7 @@ async function EdgeCertController_watchHTTPSKeyCert(
121
121
  export async function publishMachineARecords() {
122
122
  let ip = await getHostedIP();
123
123
 
124
- let machineAddress = getOwnMachineId() + "." + getDomain();
124
+ let machineAddress = getOwnMachineId(getDomain()) + "." + getDomain();
125
125
 
126
126
  let prevMachineIP = await getRecords("A", machineAddress);
127
127
  let ipDomain = await getIPDomain();
@@ -1,5 +1,5 @@
1
1
  import acme from "acme-client";
2
- import { generateRSAKeyPair, parseCert, privateKeyToPem } from "../-a-auth/certs";
2
+ import { generateRSAKeyPair, parseCert, privateKeyToPem } from "sliftutils/misc/https/certs";
3
3
  import { cache, lazy } from "socket-function/src/caching";
4
4
  import { hasDNSWritePermissions, setRecord } from "../-b-authorities/dnsAuthority";
5
5
  import { magenta } from "socket-function/src/formatting/logColors";
@@ -14,12 +14,12 @@ import { PromiseObj } from "../promise";
14
14
  import { formatDateTime } from "socket-function/src/formatting/format";
15
15
  import { isClient, isServer } from "../config2";
16
16
  import { waitForFirstTimeSync } from "socket-function/time/trueTimeShim";
17
- import { decodeNodeId, decodeNodeIdAssert } from "../-a-auth/certs";
17
+ import { decodeNodeId, decodeNodeIdAssert } from "sliftutils/misc/https/certs";
18
18
 
19
19
  import { isDefined } from "../misc";
20
20
  import { getBootedEdgeNode } from "../-0-hooks/hooks";
21
21
  import { EdgeNodeConfig } from "../4-deploy/edgeNodes";
22
- import * as certs from "../-a-auth/certs";
22
+ import * as certs from "sliftutils/misc/https/certs";
23
23
  import { logDisk } from "../diagnostics/logs/diskLogger";
24
24
  import { MaybePromise } from "socket-function/src/types";
25
25
  import { getPathStr2 } from "../path";
@@ -69,9 +69,9 @@ export function isNodeDiscoveryLogging() {
69
69
 
70
70
  function getAlternateNodeIds(nodeId: string): MaybePromise<string[] | undefined> {
71
71
  // IMPORTANT! NEVER allow for reconnection of client ids. A lot of code depends on the fact that clients will reconnect with a new client node id when they disconnect!
72
- let machineId = certs.getMachineId(nodeId);
72
+ let machineId = certs.getMachineId(nodeId, getDomain());
73
73
  if (machineId === getOwnMachineId()) {
74
- let decoded = decodeNodeId(nodeId);
74
+ let decoded = decodeNodeId(nodeId, getDomain());
75
75
  if (decoded) {
76
76
  return [
77
77
  "127-0-0-1." + decoded.domain + ":" + decoded.port
@@ -105,10 +105,10 @@ export function getOwnNodeIdAssert(): string {
105
105
  }
106
106
 
107
107
  export const getOwnThreadId = lazy(() => {
108
- return certs.getOwnThreadId();
108
+ return certs.getOwnThreadId(getDomain());
109
109
  });
110
110
  export const getOwnMachineId = lazy(() => {
111
- return certs.getOwnMachineId();
111
+ return certs.getOwnMachineId(getDomain());
112
112
  });
113
113
 
114
114
  export function isOwnNodeId(nodeId: string): boolean {
@@ -119,8 +119,8 @@ export function isOwnNodeId(nodeId: string): boolean {
119
119
  return true;
120
120
  }
121
121
  // If it's 127.0.0.1, and on the same port as us, it is us.
122
- let obj = decodeNodeId(nodeId);
123
- if (obj && obj.domain === "127-0-0-1." + getDomain() && obj.port === decodeNodeId(getOwnNodeId())?.port) {
122
+ let obj = decodeNodeId(nodeId, getDomain());
123
+ if (obj && obj.domain === "127-0-0-1." + getDomain() && obj.port === decodeNodeId(getOwnNodeId(), getDomain())?.port) {
124
124
  return true;
125
125
  }
126
126
 
@@ -128,7 +128,7 @@ export function isOwnNodeId(nodeId: string): boolean {
128
128
  }
129
129
 
130
130
  export function isNodeIdOnOwnMachineId(nodeId: string): boolean {
131
- return certs.getMachineId(nodeId) === getOwnMachineId() || decodeNodeId(nodeId)?.machineId === "127-0-0-1";
131
+ return certs.getMachineId(nodeId, getDomain()) === getOwnMachineId() || decodeNodeId(nodeId, getDomain())?.machineId === "127-0-0-1";
132
132
  }
133
133
 
134
134
  export function areNodeIdsEqual(lhs: string, rhs: string): boolean {
@@ -303,7 +303,7 @@ async function clearDeadThreadsFromArchives() {
303
303
  let nodes = await archives().find("");
304
304
 
305
305
  function getPortHash(nodeId: string) {
306
- let obj = decodeNodeId(nodeId);
306
+ let obj = decodeNodeId(nodeId, getDomain());
307
307
  if (!obj) return undefined;
308
308
  return getPathStr2(obj.machineId, obj.port + "");
309
309
  }
@@ -15,9 +15,10 @@ import type { DebugFunctionShardInfo } from "../3-path-functions/PathFunctionRun
15
15
  import type { AuthoritySpec } from "../0-path-value-core/PathRouter";
16
16
  import { requiresNetworkTrustHook } from "../-d-trust/NetworkTrust2";
17
17
  import { isNoNetwork } from "../config";
18
+ import { getDomain } from "../config";
18
19
  import { getDebuggerUrl } from "../diagnostics/listenOnDebugger";
19
20
  import { hackDevtoolsWebsocketForward } from "./oneTimeForward";
20
- import { getOwnMachineId, decodeNodeId, decodeNodeIdAssert, getMachineId } from "../-a-auth/certs";
21
+ import { getOwnMachineId, decodeNodeId, decodeNodeIdAssert, getMachineId } from "sliftutils/misc/https/certs";
21
22
  import { sort } from "socket-function/src/misc";
22
23
  import { getPathStr2 } from "../path";
23
24
  import { PromiseObj } from "../promise";
@@ -98,7 +99,7 @@ export async function getControllerNodeIdList(
98
99
  if (result) {
99
100
  let metadata = await NodeCapabilitiesController.nodes[nodeId].getMetadata();
100
101
  passedNodeIds.set(nodeId, {
101
- machineId: getMachineId(nodeId),
102
+ machineId: getMachineId(nodeId, getDomain()),
102
103
  entryPoint: metadata.entryPoint,
103
104
  });
104
105
  }
@@ -109,7 +110,7 @@ export async function getControllerNodeIdList(
109
110
  sort(results, (x) => isNodeIdOnOwnMachineId(x[0]) ? 0 : 1);
110
111
  let lookup = new Map<string, { nodeId: string; entryPoint: string }>();
111
112
  for (let x of results) {
112
- let key = getPathStr2(x[1].machineId, decodeNodeIdAssert(x[0]).port.toString());
113
+ let key = getPathStr2(x[1].machineId, decodeNodeIdAssert(x[0], getDomain()).port.toString());
113
114
  if (key in lookup) continue;
114
115
  lookup.set(key, { nodeId: x[0], entryPoint: x[1].entryPoint });
115
116
  }
@@ -12,7 +12,8 @@ import { setFlag } from "socket-function/require/compileFlags";
12
12
 
13
13
  import cbor from "cbor-x";
14
14
  import { atomicObjectWrite, atomicObjectWriteNoFreeze, doAtomicWrites } from "../2-proxy/PathValueProxyWatcher";
15
- import { getOwnThreadId } from "../-a-auth/certs";
15
+ import { getOwnThreadId } from "sliftutils/misc/https/certs";
16
+ import { getDomain } from "../config";
16
17
 
17
18
  const LAZY_INSTANCE_MARKER = Symbol("PathValueSerializer.lazyInstance");
18
19
  import { formatNumber, formatPercent, formatTime } from "socket-function/src/formatting/format";
@@ -997,7 +998,7 @@ class PathValueSerializer {
997
998
  let lazyInstance: { [k: string]: unknown } = {
998
999
  call_PathValueSerializer_getPathValue_toGetThisValue: true,
999
1000
  lazyCreatedAt: Date.now(),
1000
- lazyCreatedByThreadId: getOwnThreadId(),
1001
+ lazyCreatedByThreadId: getOwnThreadId(getDomain()),
1001
1002
  };
1002
1003
  lazyInstance[LAZY_INSTANCE_MARKER as unknown as string] = true;
1003
1004
  this.lazyValues.set(lazyInstance, buf);
@@ -1009,7 +1010,7 @@ class PathValueSerializer {
1009
1010
  let hasMarker = !!value && (value as { [k: symbol]: unknown })[LAZY_INSTANCE_MARKER] === true;
1010
1011
  let createdAt = value && value.lazyCreatedAt;
1011
1012
  let createdBy = value && value.lazyCreatedByThreadId;
1012
- return `Path: ${pathValue.path}, time: ${JSON.stringify(pathValue.time)}, currentThreadId: ${getOwnThreadId()}, hasSymbolMarker: ${hasMarker}, lazyCreatedAt: ${createdAt}, lazyCreatedByThreadId: ${createdBy}`;
1013
+ return `Path: ${pathValue.path}, time: ${JSON.stringify(pathValue.time)}, currentThreadId: ${getOwnThreadId(getDomain())}, hasSymbolMarker: ${hasMarker}, lazyCreatedAt: ${createdAt}, lazyCreatedByThreadId: ${createdBy}`;
1013
1014
  }
1014
1015
 
1015
1016
  public getPathValue(pathValue: PathValue | undefined, noMutate?: "noMutate"): unknown {
@@ -17,7 +17,8 @@ import { isClient } from "../config2";
17
17
  import { auditLog, isDebugLogEnabled } from "./auditLogs";
18
18
  import { AuthorityEntry, authorityLookup } from "./AuthorityLookup";
19
19
  import { debugNodeId } from "../-c-identity/IdentityController";
20
- import { decodeNodeId } from "../-a-auth/certs";
20
+ import { decodeNodeId } from "sliftutils/misc/https/certs";
21
+ import { getDomain } from "../config";
21
22
  import { decodeParentFilter, encodeParentFilter } from "./hackedPackedPathParentFiltering";
22
23
  import { deepCloneCborx } from "../misc/cloneHelpers";
23
24
  import { removeRange } from "../rangeMath";
@@ -352,9 +353,9 @@ class PathValueCommitter {
352
353
  timeId: value?.time.time,
353
354
  source: value?.source,
354
355
  sourceNodeId: debugNodeId(batch.sourceNodeId),
355
- sourceNodeThreadId: decodeNodeId(batch.sourceNodeId)?.threadId,
356
+ sourceNodeThreadId: decodeNodeId(batch.sourceNodeId, getDomain())?.threadId,
356
357
  watchingAuthorityId: debugNodeId(watchingAuthorityId),
357
- watchingAuthorityNodeThreadId: decodeNodeId(watchingAuthorityId)?.threadId,
358
+ watchingAuthorityNodeThreadId: decodeNodeId(watchingAuthorityId, getDomain())?.threadId,
358
359
  isTransparent: value?.isTransparent,
359
360
  });
360
361
  }
@@ -390,7 +391,7 @@ class PathValueCommitter {
390
391
  console.warn(`Ignoring parent path which we aren't watching. From ${debugNodeId(batch.sourceNodeId)}.`, {
391
392
  parentPath,
392
393
  sourceNodeId: debugNodeId(batch.sourceNodeId),
393
- sourceNodeThreadId: decodeNodeId(batch.sourceNodeId)?.threadId,
394
+ sourceNodeThreadId: decodeNodeId(batch.sourceNodeId, getDomain())?.threadId,
394
395
  });
395
396
  batch.initialTriggers.parentPaths.delete(parentPath);
396
397
  }
@@ -9,8 +9,8 @@ import { pathValueSerializer } from "../-h-path-value-serialize/PathValueSeriali
9
9
  import { pathValueCommitter } from "./PathValueCommitter";
10
10
  import { auditLog, isDebugLogEnabled } from "./auditLogs";
11
11
  import { debugNodeId, debugNodeThread } from "../-c-identity/IdentityController";
12
- import { getSlowdown, isDiskAudit } from "../config";
13
- import { decodeNodeId } from "../-a-auth/certs";
12
+ import { getSlowdown, isDiskAudit, getDomain } from "../config";
13
+ import { decodeNodeId } from "sliftutils/misc/https/certs";
14
14
  import { areNodeIdsEqual, isOwnNodeId } from "../-f-node-discovery/NodeDiscovery";
15
15
  import { getNodeIdIP } from "socket-function/src/nodeCache";
16
16
  import { authorityLookup } from "./AuthorityLookup";
@@ -160,7 +160,7 @@ export class PathValueControllerBase {
160
160
  path: value.path,
161
161
  timeId: value.time.time,
162
162
  sourceNodeId,
163
- sourceNodeThreadId: decodeNodeId(sourceNodeId)?.threadId,
163
+ sourceNodeThreadId: decodeNodeId(sourceNodeId, getDomain())?.threadId,
164
164
  totalValueCount: values.length,
165
165
  });
166
166
  }
@@ -179,7 +179,7 @@ export class PathValueControllerBase {
179
179
  timeId: value.time.time,
180
180
  timeIdVersion: value.time.version,
181
181
  sourceNodeId,
182
- sourceNodeThreadId: decodeNodeId(sourceNodeId)?.threadId,
182
+ sourceNodeThreadId: decodeNodeId(sourceNodeId, getDomain())?.threadId,
183
183
  isValid: value.valid,
184
184
  });
185
185
  }
@@ -1,6 +1,6 @@
1
1
  import { list, sort, timeInDay, timeInHour, timeInMinute, timeInSecond } from "socket-function/src/misc";
2
2
  import { MaybePromise } from "socket-function/src/types";
3
- import { decodeNodeId } from "../../-a-auth/certs";
3
+ import { decodeNodeId } from "sliftutils/misc/https/certs";
4
4
  import { getOwnNodeId, getOwnNodeIdAssert } from "../../-f-node-discovery/NodeDiscovery";
5
5
  import { pathValueArchives } from "../pathValueArchives";
6
6
  import { ArchiveLocker, ArchiveTransaction } from "./ArchiveLocks";
@@ -8,7 +8,7 @@ import { Archives } from "../../-a-archives/archives";
8
8
  import debugbreak from "debugbreak";
9
9
  import { formatNumber, formatTime } from "socket-function/src/formatting/format";
10
10
  import { blue, green, magenta, red } from "socket-function/src/formatting/logColors";
11
- import { devDebugbreak } from "../../config";
11
+ import { devDebugbreak, getDomain } from "../../config";
12
12
  import { logErrors } from "../../errors";
13
13
  import { saveSnapshot } from "./archiveSnapshots";
14
14
  import { getNodeId } from "socket-function/src/nodeCache";
@@ -395,7 +395,7 @@ class TransactionLocker {
395
395
  if (text.length <= length) return text;
396
396
  return text.slice(0, length - 3) + "...";
397
397
  }
398
- let niceThreadId = decodeNodeId(getOwnNodeIdAssert())?.threadId.slice(0, 4) || "unknown";
398
+ let niceThreadId = decodeNodeId(getOwnNodeIdAssert(), getDomain())?.threadId.slice(0, 4) || "unknown";
399
399
  function debugFileInfo(file: string) {
400
400
  let obj = pathValueArchives.decodeDataPath(file);
401
401
  if (!obj.seqNum) {
@@ -8,9 +8,9 @@ import { pathValueSerializer } from "../-h-path-value-serialize/PathValueSeriali
8
8
  import debugbreak from "debugbreak";
9
9
  import { formatNumber, formatTime } from "socket-function/src/formatting/format";
10
10
  import { list } from "socket-function/src/misc";
11
- import { NodeIdParts, decodeNodeId, decodeNodeIdAssert, encodeNodeId } from "../-a-auth/certs";
11
+ import { NodeIdParts, decodeNodeId, decodeNodeIdAssert, encodeNodeId } from "sliftutils/misc/https/certs";
12
12
  import { createArchiveLocker2 } from "./archiveLocks/ArchiveLocks2";
13
- import { devDebugbreak, isNoNetwork } from "../config";
13
+ import { devDebugbreak, isNoNetwork, getDomain } from "../config";
14
14
  import { wrapArchivesWithCache } from "../-a-archives/archiveCache";
15
15
  import { AuthoritySpec, PathRouter, debugSpec } from "./PathRouter";
16
16
  import { authorityLookup } from "./AuthorityLookup";
@@ -86,7 +86,7 @@ export class PathValueArchives {
86
86
  let parts = fileName.split("_");
87
87
  if (parts[0] !== "data") return defaultDecodedValuePath(dataPath);
88
88
  let nodeId = parts[1];
89
- let decodedNodeId = decodeNodeId(nodeId);
89
+ let decodedNodeId = decodeNodeId(nodeId, getDomain());
90
90
  if (!decodedNodeId) return defaultDecodedValuePath(dataPath);
91
91
  let time = +parts[2] || 0;
92
92
  let seqNum = +parts[3] || 0;
@@ -111,7 +111,7 @@ export class PathValueArchives {
111
111
 
112
112
  public getDefaultValuePathInput(): DecodedValuePathInput {
113
113
  return {
114
- ...decodeNodeIdAssert(getOwnNodeIdAssert()),
114
+ ...decodeNodeIdAssert(getOwnNodeIdAssert(), getDomain()),
115
115
  time: Date.now(),
116
116
  seqNum: this.nextWriteSeqNum++,
117
117
  valueCount: 0,
@@ -27,7 +27,9 @@ import { decodeParentFilter, filterChildPathsBase } from "./hackedPackedPathPare
27
27
  import { isDiskAudit } from "../config";
28
28
  import { removeRange } from "../rangeMath";
29
29
  import { remoteWatcher } from "../1-path-client/RemoteWatcher";
30
+ import { setFlag } from "socket-function/require/compileFlags";
30
31
  import { sha256 } from "js-sha256";
32
+ setFlag(require, "js-sha256", "allowclient", true);
31
33
  import { evaluateValidStates, isServer } from "../config2";
32
34
 
33
35
  setImmediate(async () => {