@ai-ecoverse/slicc-browsers 1.7.0 → 1.7.1

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
@@ -270,7 +270,13 @@ of supported names. `capabilities.scope` selects owner-specific rows.
270
270
  Map `ordinary`, `ordinary-same-site`, `seven`, `vault`, `vault-x`, `apex`, `own`
271
271
  and `client` to origins. Optionally map `plain`, `cross` and `log`; their defaults
272
272
  are `ordinary`, `client` and `ordinary`. Origins must preserve the site
273
- relationships of the data. Tags and cookie names are unique per leg. `variant`
273
+ relationships of the data. Explicitly map an unavailable target to `null`: every
274
+ row needing that origin is reported as `skip` for control, guarded and live, with
275
+ reason `not-applicable:no-<target>-origin`; no substitute origin is used and the
276
+ row never passes. A guard whose whole site is protected, such as the extension
277
+ where every `sliccy.ai` host is protected, passes `ordinary-same-site: null`.
278
+ This also applies to origins referenced in setup, triggers, observations and
279
+ liveness checks, not only the row target. Tags and cookie names are unique per leg. `variant`
274
280
  selects one variant or an array; omission selects all. `parallel` defaults to 1.
275
281
  `log(row)` receives completed rows. A variant supplies the wait before an
276
282
  explicit `Target.detachFromTarget` step and for a `settle.variant` step.
@@ -319,7 +325,12 @@ fixture log. A setup beacon on the same origin and tag cannot settle an unfinish
319
325
  redirect chain. This does not change the observations used to judge either leg.
320
326
 
321
327
  The separately exported Node module `@ai-ecoverse/slicc-browsers/fixture` exposes
322
- `fixtureServer({ host, port })`, defaulting to a random loopback port. It returns
328
+ `fixtureServer({ host, port, tls })`, defaulting to a random loopback port.
329
+ Pass `tls: { key, cert }` to serve HTTPS using Node TLS key and certificate
330
+ values. The returned origin, request logs, redirect URLs and document heartbeats
331
+ use `https://<Host>` with TLS, so `served`, `hops` and `liveCheck` compare against
332
+ the mapped HTTPS origins, including an extension client at `https://*.sliccy.ai`.
333
+ Without `tls`, the server and logged URLs remain HTTP. It returns
323
334
  `origin`, `port`, `log()`, `reset()` and `close()`. Log entries contain `url`,
324
335
  `method`, `headers` and `time`. Mirror that API when using another fixture.
325
336
  The server serves document, frame, redirect, CSP, authentication, data, image,
@@ -1,4 +1,5 @@
1
1
  import { createServer } from 'node:http';
2
+ import { createServer as createSecureServer } from 'node:https';
2
3
 
3
4
  const tall = Buffer.from(
4
5
  'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==',
@@ -75,10 +76,11 @@ function route(req, url, send, html) {
75
76
  return send(404, 'missing', 'text/plain');
76
77
  }
77
78
 
78
- export async function fixtureServer({ host = '127.0.0.1', port = 0 } = {}) {
79
+ export async function fixtureServer({ host = '127.0.0.1', port = 0, tls } = {}) {
79
80
  let entries = [];
80
- const server = createServer((req, res) => {
81
- const url = new URL(req.url, `http://${req.headers.host}`);
81
+ const scheme = tls ? 'https' : 'http';
82
+ const handler = (req, res) => {
83
+ const url = new URL(req.url, `${scheme}://${req.headers.host}`);
82
84
  entries.push({
83
85
  url: url.href,
84
86
  method: req.method,
@@ -104,7 +106,8 @@ export async function fixtureServer({ host = '127.0.0.1', port = 0 } = {}) {
104
106
  headers
105
107
  );
106
108
  route(req, url, send, html);
107
- });
109
+ };
110
+ const server = tls ? createSecureServer(tls, handler) : createServer(handler);
108
111
  await new Promise((resolve, reject) => {
109
112
  server.once('error', reject);
110
113
  server.listen(port, host, resolve);
@@ -112,7 +115,7 @@ export async function fixtureServer({ host = '127.0.0.1', port = 0 } = {}) {
112
115
  const address = server.address();
113
116
  return {
114
117
  port: address.port,
115
- origin: `http://${host}:${address.port}`,
118
+ origin: `${scheme}://${host}:${address.port}`,
116
119
  log: () => structuredClone(entries),
117
120
  reset: () => {
118
121
  entries = [];
package/guard-runner.mjs CHANGED
@@ -832,6 +832,18 @@ const inactive = (vector, target, capabilities) =>
832
832
  !supported(vector.requires, capabilities) ||
833
833
  (vector.scope !== 'any' && vector.scope !== capabilities.scope);
834
834
 
835
+ function unavailableOrigin(vector, target, targets = {}) {
836
+ const defaults = { plain: 'ordinary', cross: 'client', log: 'ordinary', own: 'client' };
837
+ const references = [target, 'plain', vector.control.origin];
838
+ for (const match of q([vector.setup, vector.trigger, vector.observe, vector.liveCheck]).matchAll(
839
+ /\{([A-Za-z][A-Za-z-]*)\}/g
840
+ ))
841
+ references.push(match[1] === 'beacon' || match[1] === 'probe' ? 'log' : match[1]);
842
+ return references
843
+ .map((name) => (targets[name] === undefined ? (defaults[name] ?? name) : name))
844
+ .find((name) => targets[name] === null);
845
+ }
846
+
835
847
  function variables(targets, target, side, slot, index) {
836
848
  const tag = `guard-${Date.now()}-${slot}-${index}-${side}-${Math.random().toString(36).slice(2)}`;
837
849
  const vars = {
@@ -860,6 +872,15 @@ async function executeRow(job, opts, clients, set, slot, index) {
860
872
  via: vector.control.via,
861
873
  transportVariant: clients.transportVariant === true,
862
874
  };
875
+ const unavailable = unavailableOrigin(vector, target, opts.targets);
876
+ if (unavailable)
877
+ return {
878
+ ...base,
879
+ control: 'skip',
880
+ guarded: 'skip',
881
+ live: 'skip',
882
+ reason: `not-applicable:no-${unavailable}-origin`,
883
+ };
863
884
  if (vector.kind === 'text')
864
885
  return {
865
886
  ...base,
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "setVersion": "1.7.0",
3
+ "setVersion": "1.7.1",
4
4
  "sources": [
5
5
  {
6
6
  "repo": "ai-ecoverse/slicc-cli",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-ecoverse/slicc-browsers",
3
- "version": "1.7.0",
3
+ "version": "1.7.1",
4
4
  "description": "SLICC's shared browser catalog, JSON schemas and discovery conformance corpus",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -64,12 +64,12 @@
64
64
  "trust": "npx fledgling sync -y --skip-publish",
65
65
  "trust:dry": "npx fledgling sync --dry-run -y --skip-publish",
66
66
  "release": "semantic-release",
67
- "test:guard": "node --test test/integration/guard-validation.test.mjs test/integration/guard-liveness.test.mjs test/integration/guard-observations.test.mjs && node scripts/test-guards.mjs",
67
+ "test:guard": "node --test test/integration/guard-fit.test.mjs test/integration/guard-validation.test.mjs test/integration/guard-liveness.test.mjs test/integration/guard-observations.test.mjs && node scripts/test-guards.mjs",
68
68
  "test:guard-target": "node --test test/integration/guard-runner.test.mjs",
69
69
  "test:unit:guard": "node --experimental-test-coverage --test --test-coverage-include=guard-runner.mjs --test-coverage-include=fixture-server.mjs --test-coverage-lines=100 test/unit/guard-*.test.mjs"
70
70
  },
71
71
  "devDependencies": {
72
- "@ai-ecoverse/slicc-shared-web": "1.17.0",
72
+ "@ai-ecoverse/slicc-shared-web": "1.19.0",
73
73
  "@biomejs/biome": "2.5.15",
74
74
  "ajv": "8.20.0",
75
75
  "ajv-formats": "3.0.1",