@ours.network/install 1.2.1-nightly.7 → 1.2.1-nightly.8

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
@@ -295,3 +295,22 @@ deletion is required; repeat the original setup with the updated installer.
295
295
  The repair runs isolated verification containers without state mounts or network
296
296
  access. Other image verification failures stop setup without replacing the image.
297
297
  An interrupted repair can be retried, including after the image tag was replaced.
298
+
299
+ ### Remote clients over HTTPS
300
+
301
+ A client may select an `https://` origin backed by a TLS reverse proxy. Keep the
302
+ daemon listener private and configure the proxy separately with a certificate
303
+ trusted by the client and matching the hostname. Node uses its normal trust
304
+ store; a private CA may be supplied through `NODE_EXTRA_CA_CERTS` before starting
305
+ the client. Certificate verification must remain enabled.
306
+
307
+ The existing issued client credential works over either transport; changing the
308
+ URL scheme does not require a new credential. Keep the server's master on the
309
+ server. Forward `x-ours-api-token` and the `x-ours-*` session headers unchanged,
310
+ and support streamed request/response bodies and long polling. Client requests
311
+ refuse redirects, including HTTPS-to-HTTP redirects: configure the final HTTPS
312
+ origin directly. UUID/capability checks still precede credential-bearing calls.
313
+
314
+ This adds client HTTPS support, not an HTTPS daemon listener, certificate
315
+ provisioning or automatic reverse-proxy configuration. Existing local HTTP and
316
+ SSH-tunnel profiles continue to work.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schema": 1,
3
3
  "channel": "nightly",
4
- "installerVersion": "1.2.1-nightly.7",
4
+ "installerVersion": "1.2.1-nightly.8",
5
5
  "packages": {
6
6
  "@ours.network/sdk": {
7
7
  "version": "3.8.1-nightly.3",
@@ -2,7 +2,7 @@
2
2
  "release": {
3
3
  "schema": 1,
4
4
  "channel": "nightly",
5
- "installerVersion": "1.2.1-nightly.7",
5
+ "installerVersion": "1.2.1-nightly.8",
6
6
  "packages": {
7
7
  "@ours.network/sdk": {
8
8
  "version": "3.8.1-nightly.3",
package/lib/effects.mjs CHANGED
@@ -1155,8 +1155,8 @@ export function networkEffects(effects) {
1155
1155
  },
1156
1156
  async discoverClientProfile(endpoint, credentialPath) {
1157
1157
  const url = new URL(endpoint);
1158
- if (url.protocol !== 'http:' || url.username || url.password || url.pathname !== '/' || url.search || url.hash)
1159
- throw new Error('Client endpoint must be an HTTP origin');
1158
+ if ((url.protocol !== 'http:' && url.protocol !== 'https:') || url.username || url.password || url.pathname !== '/' || url.search || url.hash)
1159
+ throw new Error('Client endpoint must be an HTTP or HTTPS origin');
1160
1160
  const response = await fetch(`${url.origin}/selection`, { redirect: 'error', signal: AbortSignal.timeout(5000) });
1161
1161
  if (!response.ok) throw new Error(`Daemon selection answered HTTP ${response.status}`);
1162
1162
  const selection = await response.json();
@@ -1428,7 +1428,7 @@ export async function runClientCommand(command, effects) {
1428
1428
  let profile;
1429
1429
  if (configPath) profile = validateHostProfile(effects.readProfile(configPath));
1430
1430
  else if (!command.preset && effects.interactive) {
1431
- const endpoint = await effects.askLine('Server HTTP endpoint: ', 'http://127.0.0.1:3050');
1431
+ const endpoint = await effects.askLine('Server HTTP or HTTPS endpoint: ', 'http://127.0.0.1:3050');
1432
1432
  const credentialPath = await effects.askLine('Private issued-token file: ', '');
1433
1433
  if (!credentialPath) throw new InstallUsageError('Client setup requires an issued-token file');
1434
1434
  profile = await effects.discoverClientProfile(endpoint, credentialPath);
package/lib/target.mjs CHANGED
@@ -85,15 +85,15 @@ export function validateHostProfile(value) {
85
85
  const mixed = LEGACY_PROFILE_KEYS.filter((key) => Object.hasOwn(value, key));
86
86
  if (mixed.length) throw profileError(`legacy selection keys cannot be mixed with a host profile (${mixed.join(', ')}).`);
87
87
  const { endpoint, expectedInstanceId, credentialPath } = value;
88
- if (typeof endpoint !== 'string' || endpoint.trim() !== endpoint || endpoint === '') throw profileError('endpoint must be a non-empty HTTP origin.');
88
+ if (typeof endpoint !== 'string' || endpoint.trim() !== endpoint || endpoint === '') throw profileError('endpoint must be a non-empty HTTP or HTTPS origin.');
89
89
  if (typeof expectedInstanceId !== 'string' || !PROFILE_UUID.test(expectedInstanceId)) throw profileError('expectedInstanceId must be a lowercase UUID.');
90
90
  if (typeof credentialPath !== 'string' || credentialPath === '' || !credentialPath.startsWith('/') || resolve(credentialPath) !== credentialPath) {
91
91
  throw profileError('credentialPath must be a normalized absolute path.');
92
92
  }
93
93
  let url;
94
- try { url = new URL(endpoint); } catch { throw profileError('endpoint must be an HTTP origin.'); }
95
- if (url.protocol !== 'http:' || url.username || url.password || url.pathname !== '/' || url.search || url.hash) {
96
- throw profileError('endpoint must be an HTTP origin without credentials, path, query, or fragment.');
94
+ try { url = new URL(endpoint); } catch { throw profileError('endpoint must be an HTTP or HTTPS origin.'); }
95
+ if ((url.protocol !== 'http:' && url.protocol !== 'https:') || url.username || url.password || url.pathname !== '/' || url.search || url.hash) {
96
+ throw profileError('endpoint must be an HTTP or HTTPS origin without credentials, path, query, or fragment.');
97
97
  }
98
98
  return { endpoint: url.origin, expectedInstanceId, credentialPath };
99
99
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ours.network/install",
3
- "version": "1.2.1-nightly.7",
3
+ "version": "1.2.1-nightly.8",
4
4
  "private": false,
5
5
  "description": "The all-in-one ours.network installer: one shared daemon, MCP, cowork, Telegram, Fleet initialization, harness plugins, Human identity, progress UI, and guided next steps.",
6
6
  "type": "module",