@wenathlan/saddle 1.8.5 → 1.8.7
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 +115 -104
- package/docs/actionsincident.md +33 -0
- package/docs/branchaudit.md +21 -0
- package/docs/ecosystemplan.md +3 -3
- package/docs/featureaudit.md +1 -1
- package/docs/gapmatrix.md +7 -6
- package/docs/platformpipelineaudit.md +6 -2
- package/docs/release.md +5 -5
- package/docs/releaseassets.md +16 -0
- package/docs/securityaudit-1.8.7.md +21 -0
- package/extension/README.md +2 -2
- package/extension/build.js +1 -1
- package/extension/content.js +46 -4
- package/extension/manifest.json +1 -1
- package/extension/pagebridge.js +41 -0
- package/extension/protocol.js +21 -2
- package/extension/serviceworker.js +12 -5
- package/package.json +156 -12
- package/release/assets.js +70 -0
- package/readme.txt +0 -163
- package/scrape/package-lock.json +0 -9397
- package/scrape/package.json +0 -1420
package/README.md
CHANGED
|
@@ -1,26 +1,24 @@
|
|
|
1
|
-
# Saddle
|
|
2
|
-
|
|
3
1
|
<p align="center">
|
|
4
2
|
<img src="docs/assets/saddlemark.svg" alt="Saddle" width="720" />
|
|
5
3
|
</p>
|
|
6
4
|
|
|
7
5
|
<p align="center">
|
|
8
6
|
<strong>Storage-backed jobs, scraping contracts and portable runners for Node.js.</strong><br/>
|
|
9
|
-
<strong>Binary computing
|
|
7
|
+
<strong>Binary computing engine, agent browser, scraper and packager.</strong><br/>
|
|
10
8
|
<a href="https://github.com/wenathlan/saddle/actions/workflows/ci.yml"><img src="https://github.com/wenathlan/saddle/actions/workflows/ci.yml/badge.svg" alt="CI" /></a>
|
|
11
|
-
<a href="https://github.com/wenathlan/saddle/releases/tag/v1.8.
|
|
9
|
+
<a href="https://github.com/wenathlan/saddle/releases/tag/v1.8.7"><img src="https://img.shields.io/badge/release-v1.8.7-d35d3d" alt="Release 1.8.7" /></a>
|
|
12
10
|
<a href="https://github.com/wenathlan/saddle/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-GPL--3.0-202a2f" alt="GPL 3.0 license" /></a>
|
|
13
11
|
</p>
|
|
14
12
|
|
|
15
|
-
> **Core idea:** storage is the durable side of the working set; the runner is replaceable; the artifact is the boundary. **Storage == Compute**
|
|
13
|
+
> **Core idea:** storage is the durable side of the working set; the runner is replaceable; the artifact is the boundary. **Storage == Compute** means that the same bytes can be retained or processed according to an explicit usage flag.
|
|
16
14
|
|
|
17
|
-
Saddle is a **JavaScript ESM engine** for jobs that move data between storage, a working set,
|
|
15
|
+
Saddle is a **JavaScript ESM engine** for jobs that move data between storage, a bounded working set, a caller-injected runner and durable artifacts. It is also a virtual machine published as a package: the caller can run it on GitHub Actions, Forgejo, Gitea, GitLab, Codeberg, Docker or another third-party compute surface. The engine does not require the operator's local machine, does not embed credentials and does not choose a mandatory cloud provider.
|
|
18
16
|
|
|
19
|
-
|
|
17
|
+
The canonical JavaScript package is `@wenathlan/saddle`. GitHub Packages npm, Maven and GHCR use the `wenathlan` owner namespace; NuGet and RubyGems retain their ecosystem package names. Older `@devthink`, `@iakadion` and `io.devthink` references in archived documents are historical records, not current package identities.
|
|
20
18
|
|
|
21
19
|
## Start here
|
|
22
20
|
|
|
23
|
-
Saddle requires **Node.js
|
|
21
|
+
Saddle requires **Node.js 26.7.0 or newer**.
|
|
24
22
|
|
|
25
23
|
```bash
|
|
26
24
|
npm install @wenathlan/saddle
|
|
@@ -35,160 +33,173 @@ const context = formatforagent(result, { maxchunksize: 2000, keypoints: 4 });
|
|
|
35
33
|
console.log(context.summary);
|
|
36
34
|
```
|
|
37
35
|
|
|
38
|
-
|
|
36
|
+
The deterministic examples and tests do not require network access or real credentials:
|
|
39
37
|
|
|
40
38
|
```bash
|
|
41
39
|
node examples/publicapi.js
|
|
40
|
+
npm test
|
|
42
41
|
```
|
|
43
42
|
|
|
44
|
-
##
|
|
43
|
+
## Progressive architecture
|
|
44
|
+
|
|
45
|
+
The project documentation follows a progressive arc. The foundation describes the storage and runner model; the engine describes the contracts that make the model executable; productization describes the package, extension, workflow and web surfaces.
|
|
46
|
+
|
|
47
|
+
### Foundation: storage, runners and working sets
|
|
48
|
+
|
|
49
|
+
Saddle treats a repository, bucket or object store as durable state and a third-party runner as a replaceable processor. GitHub Actions is one adapter, not the core. Forgejo, Gitea, GitLab, Codeberg, Docker and caller-owned runners can implement the same runner contracts.
|
|
50
|
+
|
|
51
|
+
The physical limit remains explicit: remote storage is not VRAM. A storage-to-RAM bridge can stage a bounded working set through a local filesystem, tmpfs, mmap, cache or caller-owned storage adapter, but it cannot remove network latency or create the bandwidth of a GPU bus. The engine exposes that distinction instead of hiding it behind marketing language.
|
|
52
|
+
|
|
53
|
+
The execution model is:
|
|
54
|
+
|
|
55
|
+
```text
|
|
56
|
+
repository or bucket -> runner working set -> process -> durable artifact
|
|
57
|
+
persistent state virtual processor published boundary
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
The repository may act as a disk, a CI workflow may act as a function call, Pages may act as a static bus and a release artifact may act as the durable boundary. `workflow_dispatch`, `repository_dispatch` and HTTP adapters remain caller-configured interfaces.
|
|
61
|
+
|
|
62
|
+
### Engine: contracts instead of vendor lock-in
|
|
45
63
|
|
|
46
|
-
| Area |
|
|
64
|
+
| Area | Contracts shipped | Result |
|
|
47
65
|
| --- | --- | --- |
|
|
48
|
-
| Jobs | `engine`, `scheduler`, `inprocess` | `prepare
|
|
49
|
-
| Storage | local, chunked, content-addressed, S3-compatible, GitHub Contents
|
|
50
|
-
| Working set | memory bridge, modes, objects
|
|
51
|
-
| Scraping | robots, cache, extraction, semantic facts, schema
|
|
52
|
-
| Crawl | normalization, priority frontier, BFS crawler
|
|
53
|
-
| Browser | snapshots, tabs, frames, actions, fingerprint, session
|
|
66
|
+
| Jobs | `engine`, `scheduler`, `inprocess` | `prepare -> process -> sync -> cleanup` |
|
|
67
|
+
| Storage | local, chunked, content-addressed, S3-compatible, GitHub Contents and file-hosting adapters | durable objects, ranges, dedupe and sync |
|
|
68
|
+
| Working set | memory bridge, modes, objects and transforms | storage-to-compute and compute-to-storage flows |
|
|
69
|
+
| Scraping | robots, cache, extraction, semantic facts, schema and normalization | bounded text, metadata, links, controls and structured output |
|
|
70
|
+
| Crawl | normalization, priority frontier, BFS crawler and persistent frontier contracts | domain-aware bounded crawling |
|
|
71
|
+
| Browser | snapshots, tabs, frames, actions, fingerprint, session and replay contracts | caller-owned browser automation without a mandatory provider |
|
|
54
72
|
| Operations | queues, idempotency, saga, retry, circuit breaker, health and heartbeat | controlled execution and recovery |
|
|
55
73
|
| Protocols | JSON, NDJSON, SSE, blocks, API envelopes and MCP | transport-neutral messages |
|
|
56
|
-
| Delivery | manifests, workflow registry,
|
|
74
|
+
| Delivery | manifests, workflow registry, extension packaging and release assets | repeatable package and runner surfaces |
|
|
57
75
|
| Integrations | GitHub, GitLab, Forgejo, app lifecycle, command scopes and delivery adapters | caller-owned provider connectivity |
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
76
|
+
|
|
77
|
+
The root entry point is transport-neutral. Node filesystem, HTTP server, persistent sessions and Playwright are explicit subpaths or optional adapters. The library accepts caller-provided fetchers, browser transports, storage adapters, persistence, proxy pools, captcha evidence handlers, webhook secrets and remote credentials.
|
|
78
|
+
|
|
79
|
+
### Productization: one engine, many shells
|
|
80
|
+
|
|
81
|
+
The same contracts can be surfaced as an npm library, CLI, binary, Manifest V3 browser extension, webhook server, MCP transport, workflow action, container image, Maven package, NuGet package or RubyGem. These surfaces are adapters around the engine; they are not separate sources of truth.
|
|
62
82
|
|
|
63
83
|
## Public API
|
|
64
84
|
|
|
65
85
|
| Export | Purpose |
|
|
66
86
|
| --- | --- |
|
|
67
|
-
| `saddleurl` | choose fetch or injected browser path |
|
|
68
|
-
| `scrapeurl` | fetch one URL and extract |
|
|
69
|
-
| `scrapehtml` | extract from HTML without network |
|
|
87
|
+
| `saddleurl` | choose a fetch or caller-injected browser path |
|
|
88
|
+
| `scrapeurl` | fetch one URL and extract bounded content |
|
|
89
|
+
| `scrapehtml` | extract from HTML without network access |
|
|
70
90
|
| `extractcontent` | structured extraction |
|
|
71
|
-
| `serializeresult` | serialize
|
|
72
|
-
| `formatforagent` | summary, chunks
|
|
91
|
+
| `serializeresult` | serialize JSON, Markdown or XML results |
|
|
92
|
+
| `formatforagent` | summary, chunks and token count |
|
|
73
93
|
| `batchscrape` | bounded URL groups |
|
|
74
|
-
| `crawlurl` | crawl contract |
|
|
75
|
-
| `browseragent` | navigation, click, type
|
|
76
|
-
| `mcpserver` / `mcptransport` | MCP tools over JSONL
|
|
94
|
+
| `crawlurl` | crawl contract with domain and budget controls |
|
|
95
|
+
| `browseragent` | caller-owned navigation, click, type and screenshot actions |
|
|
96
|
+
| `mcpserver` / `mcptransport` | MCP tools over JSONL or HTTP |
|
|
77
97
|
| `nodeserver` | Web Request/Response handler |
|
|
98
|
+
| `engine` / `scheduler` | job lifecycle and runner dispatch |
|
|
99
|
+
| `release-assets` | SHA256SUMS, SBOM and provenance metadata for caller-selected artifacts |
|
|
78
100
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
## The execution model
|
|
82
|
-
|
|
83
|
-
Saddle coordinates contracts instead of hiding providers. A repo + CI runner is a virtual processor:
|
|
84
|
-
|
|
85
|
-
- Repo = Disk (persistent state)
|
|
86
|
-
- CI = CPU (workflow_dispatch = function call)
|
|
87
|
-
- Pages = Bus + CDN
|
|
88
|
-
- Static site = BIOS
|
|
89
|
-
- repository_dispatch = IPC
|
|
90
|
-
|
|
91
|
-
```js
|
|
92
|
-
import { engine, eventbus, inprocess, scheduler } from "@wenathlan/saddle";
|
|
93
|
-
import { localmemory } from "@wenathlan/saddle/memory-node";
|
|
94
|
-
import { localstorage } from "@wenathlan/saddle/storage-node";
|
|
95
|
-
const events = eventbus();
|
|
96
|
-
const run = engine({
|
|
97
|
-
storage: localstorage("./.saddle-data"),
|
|
98
|
-
memory: localmemory(),
|
|
99
|
-
scheduler: scheduler([inprocess()]),
|
|
100
|
-
events
|
|
101
|
-
});
|
|
102
|
-
const result = await run.run(
|
|
103
|
-
{ name: "example", input: { value: 42 } },
|
|
104
|
-
({ job }) => ({ jobid: job.id, ok: true })
|
|
105
|
-
);
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
The caller still chooses how to provide `fetcher`, browser transport, persistence, proxy pool, captcha solver, webhook secret and remote credentials. The root entry is transport-neutral; Node filesystem and HTTP adapters are explicit subpaths such as `@wenathlan/saddle/storage-node`, `@wenathlan/saddle/memory-node`, `@wenathlan/saddle/server-node`, `@wenathlan/saddle/sessions-file` and `@wenathlan/saddle/queue-persistent`. Saddle does not embed secrets, fixed hosts or a mandatory cloud vendor.
|
|
101
|
+
The complete export map is documented in [`docs/libraryapi.md`](docs/libraryapi.md). The product index is in [`docs/productindex.md`](docs/productindex.md), and runnable examples are in [`docs/usage.md`](docs/usage.md).
|
|
109
102
|
|
|
110
103
|
## Browser extension
|
|
111
104
|
|
|
112
|
-
|
|
105
|
+
The extension is a pure JavaScript Manifest V3 reference surface in [`extension/`](extension/). It contains a popup, service worker, isolated content bridge, read-only page-world `pagefacts` boundary, snapshot diffs and persisted window/tab/frame context for explicit resume.
|
|
113
106
|
|
|
114
107
|
```bash
|
|
115
108
|
# load the unpacked extension from chrome://extensions
|
|
116
109
|
ls extension/manifest.json extension/worker.js extension/content.js extension/popup.html
|
|
117
110
|
|
|
118
|
-
# build an isolated
|
|
111
|
+
# build an isolated artifact using the version supplied by the caller or release tag
|
|
119
112
|
npm run extension:build -- --output build/extension
|
|
120
113
|
```
|
|
121
114
|
|
|
122
|
-
The
|
|
115
|
+
The base permission set is `activeTab`, `scripting` and `storage`. It does not request broad host permissions, cookies, `webRequest`, debugger access or arbitrary page code execution. Optional host escalation remains caller-owned. Releases attach `saddle-extension-<version>.zip`; cross-browser profiles remain adapter work.
|
|
123
116
|
|
|
124
|
-
##
|
|
117
|
+
## Security boundaries
|
|
118
|
+
|
|
119
|
+
| Boundary | Policy |
|
|
120
|
+
| --- | --- |
|
|
121
|
+
| Credentials | injected by the caller or repository secret; never committed or printed |
|
|
122
|
+
| Network | HTTP/HTTPS targets are validated; private-target access remains caller policy |
|
|
123
|
+
| Crawling | robots rules, crawl delay, limits and budgets are explicit |
|
|
124
|
+
| Storage | adapters are replaceable; the core does not own a provider account |
|
|
125
|
+
| Runtime | Node-only filesystem, HTTP, Playwright and release metadata stay outside the transport-neutral root |
|
|
126
|
+
| Extension | page-world reads are bounded, token-correlated and read-only |
|
|
127
|
+
| Failure | retry, circuit breaker, idempotency and resume are configurable |
|
|
128
|
+
| Releases | version comes from the `vX.Y.Z` tag and must match `package.json` |
|
|
129
|
+
|
|
130
|
+
Version 1.8.7 also removes the obsolete nested `scrape` package manifests and lockfile that generated a separate stale dependency graph. The dependency-free JavaScript scrape contracts remain in `scrape/`. The root lockfile is regenerated and CI runs `npm audit --audit-level=high` plus dependency review for pull requests. See [`docs/securityaudit-1.8.7.md`](docs/securityaudit-1.8.7.md) for the baseline and remediation record.
|
|
131
|
+
|
|
132
|
+
## Package surfaces and release automation
|
|
133
|
+
|
|
134
|
+
Workflows use the release tag and the local `releaseversion` action. They do not contain a manually edited version number. The action fetches the tag, checks out its commit and rejects a release when the tag version does not match the root `package.json`.
|
|
135
|
+
|
|
136
|
+
| Registry | Artifact | Workflow |
|
|
137
|
+
| --- | --- | --- |
|
|
138
|
+
| GitHub Packages npm | `@wenathlan/saddle@<version>` | `publishgithubnpm.yml` |
|
|
139
|
+
| Public npmjs | `@wenathlan/saddle@<version>` | `publishnpmjs.yml` |
|
|
140
|
+
| GHCR | `ghcr.io/wenathlan/saddle:<version>` | `publishghcr.yml` |
|
|
141
|
+
| Maven | `io.wenathlan:saddle:<version>` | `publishmaven.yml` |
|
|
142
|
+
| NuGet | `Saddle.<version>.nupkg` | `publishnuget.yml` |
|
|
143
|
+
| RubyGems | `saddle <version>` | `publishrubygems.yml` |
|
|
144
|
+
|
|
145
|
+
Release assets are caller-selected and deterministic: `SHA256SUMS`, `sbom.cdx.json` in CycloneDX 1.5 shape and `provenance.intoto.jsonl` in an in-toto statement shape. The adapter does not publish, authenticate or choose a registry. The npm token previously sent in chat is compromised and must never be used; public npmjs publication uses only the owner-managed `NPM_TOKEN` repository secret.
|
|
146
|
+
|
|
147
|
+
## GitHub Pages web surface
|
|
148
|
+
|
|
149
|
+
The marketing site lives under [`web/`](web/) with a root-based TypeScript/React layout. It has no `client/` or `src/` subdirectory. Vite normalizes the base path and all visual assets resolve through a shared helper, so the same build works at `/` and `/saddle/`.
|
|
125
150
|
|
|
126
151
|
```bash
|
|
127
|
-
|
|
128
|
-
saddle
|
|
129
|
-
saddle runexample
|
|
130
|
-
saddle mcp
|
|
152
|
+
npm run web:check
|
|
153
|
+
VITE_BASE_PATH=/saddle npm run web:build:pages
|
|
131
154
|
```
|
|
132
155
|
|
|
133
|
-
|
|
156
|
+
Small public configuration and visual assets live under `web/public/`. The development collector is `web/public/debugcollector.js` and uses `/debuglogs`; it is not part of the production build. The obsolete `web/public/__manus__` directory is intentionally absent.
|
|
134
157
|
|
|
135
|
-
|
|
136
|
-
| --- | --- |
|
|
137
|
-
| Credentials | injected at runtime; never committed |
|
|
138
|
-
| Network | http/https validated; private targets blocked |
|
|
139
|
-
| Crawling | robots rules and crawl delay explicit |
|
|
140
|
-
| Storage | adapters replaceable |
|
|
141
|
-
| Runtime | Node HTTP isolated |
|
|
142
|
-
| Failure | retry, circuit breaker, idempotency configurable |
|
|
143
|
-
|
|
144
|
-
## Package surfaces
|
|
145
|
-
|
|
146
|
-
| Registry | Artifact | Workflow | Status |
|
|
147
|
-
| --- | --- | --- | --- |
|
|
148
|
-
| GitHub npm | `@wenathlan/saddle@1.8.5` | publishgithubnpm.yml | pending release |
|
|
149
|
-
| GHCR | `ghcr.io/wenathlan/saddle:1.8.5` and `latest` | publishghcr.yml | pending release |
|
|
150
|
-
| Maven | `io.wenathlan:saddle:1.8.5` | publishmaven.yml | pending release |
|
|
151
|
-
| NuGet | `Saddle.1.8.5.nupkg` | publishnuget.yml | pending release |
|
|
152
|
-
| RubyGems | `saddle 1.8.5` | publishrubygems.yml | pending release |
|
|
153
|
-
| npmjs | `@wenathlan/saddle@1.8.5` | publishnpmjs.yml | pending release |
|
|
154
|
-
|
|
155
|
-
## Development
|
|
158
|
+
## Development and release gates
|
|
156
159
|
|
|
157
160
|
```bash
|
|
158
161
|
npm ci
|
|
159
|
-
npm test
|
|
160
162
|
npm run check
|
|
161
163
|
npm run formatcheck
|
|
164
|
+
npm test
|
|
162
165
|
npm run pack:check
|
|
166
|
+
npm audit --audit-level=high
|
|
167
|
+
npm run web:check
|
|
168
|
+
VITE_BASE_PATH=/saddle npm run web:build:pages
|
|
163
169
|
```
|
|
164
170
|
|
|
165
|
-
|
|
171
|
+
The engine test suite is deterministic and does not require real credentials or network access. The release path is: update `package.json` and the manifest files, update `changelog.md`, run all gates, create `v<package-version>`, push the tag and create the GitHub release. Registry workflows then derive the same version from that release tag.
|
|
166
172
|
|
|
167
173
|
## Repository map
|
|
168
174
|
|
|
169
|
-
```
|
|
170
|
-
core/ errors, events and
|
|
175
|
+
```text
|
|
176
|
+
core/ errors, events, identifiers and hashing
|
|
171
177
|
domain/ jobs, artifacts, sessions and providers
|
|
172
178
|
memory/ working-set bridge, modes, objects and transforms
|
|
173
179
|
storage/ local, chunked, remote and file-hosting adapters
|
|
174
|
-
scrape/ robots, cache, extraction, schema and
|
|
180
|
+
scrape/ dependency-free robots, cache, extraction, schema and normalization contracts
|
|
175
181
|
crawl/ URL normalization, crawler and persistent frontier
|
|
176
182
|
queue/ queue, idempotency, saga and recovery
|
|
177
|
-
browser/ fingerprint, session and
|
|
178
|
-
|
|
179
|
-
mcp/ optional server and JSONL/HTTP transport
|
|
183
|
+
browser/ fingerprint, session, agent and Playwright adapter contracts
|
|
184
|
+
extension/ Manifest V3 reference surface and packager
|
|
180
185
|
protocol/ JSON, NDJSON, SSE and block serializers
|
|
181
|
-
workflow/ manifests, templates and registry
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
186
|
+
workflow/ manifests, templates and registry contracts
|
|
187
|
+
packager/ package and publication plans
|
|
188
|
+
release/ checksums, SBOM and provenance metadata
|
|
189
|
+
web/ root-based static marketing site
|
|
190
|
+
tests/ deterministic engine and extension coverage
|
|
191
|
+
docs/ architecture, API, security, release and registry notes
|
|
185
192
|
```
|
|
186
193
|
|
|
187
|
-
|
|
194
|
+
The engine remains pure JavaScript ESM with JSDoc comments in English. The web surface is TypeScript/React, while the published library has no TypeScript build requirement and no hardcoded host, port or credential.
|
|
195
|
+
|
|
196
|
+
## Historical documentation
|
|
197
|
+
|
|
198
|
+
Earlier README snapshots remain in `docs/plans/README.md`, `docs/talks9/README.md` and `docs/talks9/README (2).md` as archival evidence. Their useful architecture ideas were consolidated here, while stale `@devthink`, `@iakadion`, `io.devthink`, Node 20/22, `client/src` and speculative provider quotas were not copied into the canonical contract.
|
|
188
199
|
|
|
189
200
|
## Current scope
|
|
190
201
|
|
|
191
|
-
Version 1.8.
|
|
202
|
+
Version 1.8.7 extends the 1.8.6 engine with dependency remediation, explicit security gates, base-aware Pages assets, removal of the obsolete public debug directory and consolidated documentation. Browser binaries, provider credentials, n8n host registration, persistent databases, captcha solvers and production deployment remain caller-selected adapters. Future work should extend contracts without coupling the core to one forge, registry, browser or storage vendor.
|
|
192
203
|
|
|
193
204
|
## License
|
|
194
205
|
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Actions and Pages incident
|
|
2
|
+
|
|
3
|
+
This note records the GitHub-hosted failures observed while debugging the root web migration on 2026-08-13. The repository is public, the default branch is `main`, and the GitHub API reported `has_pages: false` before Pages configuration.
|
|
4
|
+
|
|
5
|
+
## observed failures
|
|
6
|
+
|
|
7
|
+
| Surface | Run | Evidence |
|
|
8
|
+
| --- | --- | --- |
|
|
9
|
+
| GitHub Pages | [31703685525](https://github.com/wenathlan/saddle/actions/runs/31703685525) | `actions/configure-pages@v5` returned `HttpError: Not Found`; the repository Pages site was not enabled/configured. |
|
|
10
|
+
| CI | [31703407943](https://github.com/wenathlan/saddle/actions/runs/31703407943) | The historical workflow invoked `npm run build`, which is not a root package script. |
|
|
11
|
+
| Uka tests | [31702858313](https://github.com/wenathlan/saddle/actions/runs/31702858313) | The historical workflow invoked `npm run typecheck`, which is not a root package script. |
|
|
12
|
+
| CI | [31702858281](https://github.com/wenathlan/saddle/actions/runs/31702858281) | The historical workflow invoked both `npm run typecheck` and `npm run build`, which are not the engine gates. |
|
|
13
|
+
| Dependabot | [31701834922](https://github.com/wenathlan/saddle/actions/runs/31701834922) | Dependabot attempted `/web/package.json`, which was intentionally removed during the root migration. |
|
|
14
|
+
|
|
15
|
+
## correction contract
|
|
16
|
+
|
|
17
|
+
The canonical npm manifest and lockfile are at the repository root. Engine workflows must use `npm ci`, `npm run check`, `npm run formatcheck`, `npm test` and `npm run pack:check`. The web Pages workflow must use `npm run web:check`, `npm run web:build:pages` and publish `web/dist/public`. Dependabot must use the `npm` ecosystem at `/`.
|
|
18
|
+
|
|
19
|
+
The Pages workflow also requires the repository owner to enable GitHub Pages and select **GitHub Actions** as its source. The workflow cannot create the Pages site when the repository API still reports `has_pages: false`; that setting is managed at the repository level, not by the static artifact build.
|
|
20
|
+
|
|
21
|
+
After selecting **GitHub Actions** in the repository settings, the Pages API reported `has_pages: true`, `build_type: workflow`, source `main` and the public URL `https://wenathlan.github.io/saddle/`. The corrected build/deploy workflow then completed successfully in [run 31705301175](https://github.com/wenathlan/saddle/actions/runs/31705301175), with `configure pages`, `web:check`, build, artifact upload and deploy all green.
|
|
22
|
+
|
|
23
|
+
The final workflow commits also passed [Saddle engine CI run 31705367442](https://github.com/wenathlan/saddle/actions/runs/31705367442), [Uka-tests run 31705367433](https://github.com/wenathlan/saddle/actions/runs/31705367433) and [cross-runtime compatibility run 31705367432](https://github.com/wenathlan/saddle/actions/runs/31705367432). All three completed with `success` on `main`.
|
|
24
|
+
|
|
25
|
+
The repository metadata audit found `main` as the default branch and one open Dependabot pull request (`#4`, branch `dependabot/npm_and_yarn/npm_and_yarn-2772e86c4e`). Its only commit (`4cb2a45`) changes the root package lock plus an unrelated nested `scrape/package.json` and `scrape/package-lock.json`; it does not represent a second production branch and is not safe to merge into the root release. The branch should be closed as an obsolete automated update after owner confirmation.
|
|
26
|
+
|
|
27
|
+
The repository homepage About editor was opened in the authenticated browser and saved with the canonical Saddle description. The repository API should now report that description instead of the placeholder `saddle`.
|
|
28
|
+
|
|
29
|
+
The six non-main Dependabot tips were preserved as `archive-dependabot-*` tags, their PRs were closed, and their branch refs were removed. The cleanup leaves `main` as the only active branch without deleting the archived commit objects.
|
|
30
|
+
|
|
31
|
+
The first `v1.8.6` release fan-out passed release validation, GitHub Packages npm, public npmjs, Maven, NuGet, RubyGems and extension packaging. GHCR alone failed because the Docker image ran `npm ci --omit=dev` against the root manifest, whose dev-only Vite peer graph is rejected by npm's strict peer resolver. The corrective Dockerfile now sets `NPM_CONFIG_LEGACY_PEER_DEPS=true` and passes `--legacy-peer-deps`; the GHCR workflow also checks out the release tag for both release and manual dispatch paths.
|
|
32
|
+
|
|
33
|
+
The corrected manual GHCR run [31706464064](https://github.com/wenathlan/saddle/actions/runs/31706464064) completed successfully, including the Docker build and push. The six registry outcomes for `v1.8.6` are therefore green: GitHub Packages npm, public npmjs, Maven, NuGet, RubyGems and GHCR. The Pages deployment remains green in [run 31705301175](https://github.com/wenathlan/saddle/actions/runs/31705301175).
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Branch audit
|
|
2
|
+
|
|
3
|
+
This record preserves the branch tips and comparison results collected before the branch cleanup. Deleting a branch reference does not delete the commit objects or the tags that retain them; the hashes below remain available for audit and recovery while repository retention permits.
|
|
4
|
+
|
|
5
|
+
| Branch | Tip commit | Ahead of `main` | Behind `main` | Unique change | Action |
|
|
6
|
+
| --- | --- | ---: | ---: | --- | --- |
|
|
7
|
+
| `main` | `04acff11e7f3c0bc830fdaaf1fc7bad9bdf1fcfa` | 0 | 0 | Current release line | Keep |
|
|
8
|
+
| `dependabot/npm_and_yarn/lucide-react-1.31.0` | `45498007cc539d2c3df3d801cfb23dfdf575d859` | 1 | 11 | `package.json`, `package-lock.json` | Close PR #9 and delete branch |
|
|
9
|
+
| `dependabot/npm_and_yarn/multi-b251156d90` | `cff1abfbcfe6fffae1a5517082c76b9f3e6195ea` | 1 | 11 | `package.json`, `package-lock.json` | Close PR #7 and delete branch |
|
|
10
|
+
| `dependabot/npm_and_yarn/npm_and_yarn-2772e86c4e` | `4cb2a45cc8dd1bc53b05b5ffe8eeb07c1c46bc1c` | 1 | 13 | Root package files plus obsolete `scrape/` package files | Close PR #4 and delete branch |
|
|
11
|
+
| `dependabot/npm_and_yarn/react-resizable-panels-4.12.2` | `8dfa1d1999c6cf0b80d39f54c1194499c2943739` | 1 | 11 | `package.json`, `package-lock.json` | Close PR #5 and delete branch |
|
|
12
|
+
| `dependabot/npm_and_yarn/streamdown-2.5.0` | `ac04d2d01c2caa3c0bb9a8b7e8b952fd0af4b2d6` | 1 | 11 | `package.json`, `package-lock.json` | Close PR #6 and delete branch |
|
|
13
|
+
| `dependabot/npm_and_yarn/typescript-7.0.2` | `7d5d3f7b70d28ed2663a6d9b2d4f8a3280571525` | 1 | 11 | `package.json`, `package-lock.json` | Close PR #8 and delete branch |
|
|
14
|
+
|
|
15
|
+
All six non-main branches are single-commit Dependabot updates based on an older main tip. None is a second production line, and none should be merged blindly after the root web migration. The current `main` line keeps the release work; the branch tips above remain referenced by this audit until the remote branch refs are removed.
|
|
16
|
+
|
|
17
|
+
The cleanup was completed by creating the six `archive-dependabot-*` tags, closing PRs #4 through #9, and deleting the six non-main branch refs. The repository is now intentionally reduced to `main`; the archive tags preserve the exact tips listed above.
|
|
18
|
+
|
|
19
|
+
## Checks interpretation
|
|
20
|
+
|
|
21
|
+
The check count changed because the workflow set changed during the root migration. Duplicate and obsolete workflow definitions were removed, while the canonical engine CI, Uka-tests, cross-runtime compatibility and Pages workflows were retained. The final `main` workflow set passed the current checks; a lower count therefore reflects fewer active check definitions, not a loss of commits or a failed release line.
|
package/docs/ecosystemplan.md
CHANGED
|
@@ -26,13 +26,13 @@ The engine owns **contracts, validation, orchestration, recovery and auditabilit
|
|
|
26
26
|
| --- | --- | --- | --- |
|
|
27
27
|
| 1 | audit and governance | active | gap matrix, sources, claims reconciled |
|
|
28
28
|
| 2 | browser agent foundation | complete | snapshots, refs, stale errors, tabs, frames, action results and context-aware replay provenance tests |
|
|
29
|
-
| 3 | extension runtime | first slice complete | MV3 unpacked surface, protocol, worker, content bridge and tests |
|
|
29
|
+
| 3 | extension runtime | first slice complete | MV3 unpacked surface, protocol, worker, isolated content bridge, read-only page boundary and tests |
|
|
30
30
|
| 4 | working set and storage | complete | range chunks, content dedupe, tiered cache, conflict sync and memory capabilities |
|
|
31
31
|
| 5 | runners and execution | complete | provider health, triggers, cancellation, heartbeat and resumable runs |
|
|
32
32
|
| 6 | scraping and context | complete | semantic extraction, content-type normalization, crawl budgets, RAG lineage and low-cardinality metrics |
|
|
33
33
|
| 7 | API, MCP and security | complete | request identity, optional auth, secure headers, browser MCP tools and redirect/DNS checks |
|
|
34
34
|
| 8 | bots and integrations | complete | app lifecycle, command scopes, idempotency, delivery retries and dead letters |
|
|
35
|
-
| 9 | packaging and distribution | extension zip and
|
|
35
|
+
| 9 | packaging and distribution | extension zip, checksum, SBOM and provenance slice implemented | desktop, mobile, n8n and binary artifacts remain caller-owned |
|
|
36
36
|
| 10 | product surfaces and operations | first slice complete | desktop, mobile, n8n and operator control contracts; observability, retention and threat model remain |
|
|
37
37
|
| 11 | cross-runtime compatibility | transport-neutral graph audit complete | Node, Bun and Deno root probe, browser worker bridge, extension permission/build checks and package graph audit |
|
|
38
38
|
| 12 | release gates | active | deterministic checks, docs, clean diffs and claim/code parity |
|
|
@@ -52,7 +52,7 @@ Each block follows the same loop:
|
|
|
52
52
|
|
|
53
53
|
## current implementation
|
|
54
54
|
|
|
55
|
-
Version 1.8.
|
|
55
|
+
Version 1.8.6 carries the public npm identity migration through the transferred `wenathlan` repository owner, aligns GitHub Packages npm, Maven and GHCR owner metadata, and includes the minimal extension permission policy, deterministic extension zip workflow, context-aware replay, transport-neutral graph audit, bounded content normalization, isolated page facts, snapshot context diffs, reproducible release assets and root-based Pages deployment. Registry publication is triggered only after the release tag and independent target checks. The first product surface slice adds desktop, mobile, n8n, operator control, operational policy and framework-neutral HTTP contracts. The first cross-runtime slice validates the root on Node, Bun and Deno, while extension-context and browser bundler checks remain caller-owned.
|
|
56
56
|
|
|
57
57
|
## evidence sources
|
|
58
58
|
|
package/docs/featureaudit.md
CHANGED
|
@@ -51,7 +51,7 @@ This audit compares the current repository with the project README and the addit
|
|
|
51
51
|
| GitHub Packages and GHCR | missing | no package or image publishing jobs |
|
|
52
52
|
| Maven, NuGet, RubyGems, PyPI | missing | no language specific wrappers or trusted publishing jobs |
|
|
53
53
|
| jsDelivr, UNPKG, esm.sh | partial | URLs are documented; no release verification or SRI manifest |
|
|
54
|
-
| browser extension | partial |
|
|
54
|
+
| browser extension | partial | MV3 source, minimal permissions, isolated page boundary, snapshot diffs and unpacked zip build exist; CRX signing and cross-browser profiles remain caller-owned |
|
|
55
55
|
| mobile and desktop apps | partial | target manifests only; no Tauri, Capacitor, Android, or iOS project |
|
|
56
56
|
| site and per site database | missing | no `web` application, Hono server, Drizzle schema, Prisma schema, or site deployment adapter |
|
|
57
57
|
| multi platform app identity | partial | generic bot and forge contracts; no OAuth or GitHub App installation flow |
|
package/docs/gapmatrix.md
CHANGED
|
@@ -15,15 +15,15 @@ This matrix turns the supplied README and conclusions into implementation decisi
|
|
|
15
15
|
|
|
16
16
|
| Area | Current state | Gap | Priority | Decision |
|
|
17
17
|
| --- | --- | --- | --- | --- |
|
|
18
|
-
| Root library | Implemented ESM entry point with broad exports
|
|
18
|
+
| Root library | Implemented ESM entry point with broad exports and an extension subpath | Browser-specific packaging and cross-browser profiles remain adapter-owned | P2 | Keep serializable extension contracts separate from browser binaries |
|
|
19
19
|
| Browser agent | Implemented injected action adapter for navigate, click, type, screenshot, DOM, title, scroll and command batches | Vendor-neutral action results and bounded action batches are public; optional Playwright provider is isolated behind `browser-playwright` | P1 | Keep the adapter boundary; browser binaries and credentials remain caller-owned |
|
|
20
20
|
| Browser snapshots | Implemented public contract | Snapshot ids, bounded elements, stable refs, stale checks and diffs are covered by deterministic tests | P0 | Reuse the contract from MCP and extension transport |
|
|
21
21
|
| Session replay | Implemented | Replay restores caller-owned window, tab and frame context before actions; context identifiers are validated and counted | P1 | Keep browser selection and restoration in injected adapters |
|
|
22
|
-
| Extension runtime |
|
|
23
|
-
| Extension messaging |
|
|
22
|
+
| Extension runtime | Manifest V3 manifest, service worker, content bridge, popup, snapshot diffs, context metadata and deterministic build artifact are implemented | Cross-browser manifests remain unbundled | P2 | Keep a pure JavaScript MV3 reference surface with minimal permissions |
|
|
23
|
+
| Extension messaging | Versioned envelope, correlation id, timeout, sender metadata and error response contract are implemented | Long-lived ports remain caller-owned | P1 | Keep transport-neutral messages and explicit runtime adapters |
|
|
24
24
|
| Service worker resilience | Implemented contract slice | Pending command envelopes, attempt metadata and snapshot summaries persist through injected storage; resume remains explicit and user-owned | P0 | Rehydrate metadata on startup and never replay a command without an explicit caller action |
|
|
25
25
|
| Permissions | Contract slice | `permissionpolicy` keeps the base permissions minimal and optional escalation caller-owned | P0 | Start with `storage` and no broad host permissions; make host access caller-configured |
|
|
26
|
-
| Content isolation |
|
|
26
|
+
| Content isolation | Implemented read-only page-to-extension boundary | The page world cannot invoke extension commands; richer page facts remain bounded | P1 | Keep `pagebridge.js` read-only, token-correlated and caller-controlled |
|
|
27
27
|
| Task agent | Partial | Jobs, workflows and bot commands exist, but no browser task planner or tool registry | P1 | Reuse workflow, trigger and bot contracts; add browser task commands only after snapshots |
|
|
28
28
|
| MCP | Implemented scrape, crawl, batch, extract and serialize tools with JSON-RPC handling | No browser snapshot or browser action MCP tools | P1 | Add browser tools as an optional adapter over the same snapshot/action contracts |
|
|
29
29
|
| API security | Implemented URL protocol and private hostname/IP checks | Request envelopes, optional authorization, security headers, redirect bounds and injected DNS resolution checks are now available | P0 | Keep credentials caller-owned and reject private or rebinding targets before transport |
|
|
@@ -40,7 +40,7 @@ This matrix turns the supplied README and conclusions into implementation decisi
|
|
|
40
40
|
| Auth profiles | Session file and replay contracts exist | No extension profile or consent model | P1 | Defer cookie/profile export; support explicit user-owned session references only |
|
|
41
41
|
| CAPTCHA | Contract, guard and evidence exist | No automatic solver integration | deferred | Keep external/manual solver boundary; do not promise bypass in the extension |
|
|
42
42
|
| Stealth | Fingerprint contract exists | No automatic stealth patching | deferred | Keep opt-in fingerprint metadata; no hidden anti-detection behavior |
|
|
43
|
-
| Packaging | npm, GHCR, Maven, NuGet, RubyGems
|
|
43
|
+
| Packaging | npm, GHCR, Maven, NuGet, RubyGems, extension zip, deterministic SHA256SUMS, CycloneDX SBOM and in-toto-shaped provenance assets are implemented | Desktop, mobile, n8n and binary release artifacts remain caller-owned | P1 | Keep non-JavaScript artifacts in explicit adapters and release jobs |
|
|
44
44
|
| Mobile and desktop apps | Contract slice | Desktop/mobile manifests and caller-owned adapter contracts exist; no native project is bundled | P1 | Keep native projects caller-owned and add runtime conformance tests incrementally |
|
|
45
45
|
| n8n surface | Contract slice | Node metadata, trigger matching and declared action execution exist; no n8n host package is bundled | P1 | Keep node registration and credentials caller-owned |
|
|
46
46
|
| Cross-browser | Target profile declares browser and extension | Firefox, Edge or Safari manifests remain unbundled; transport-neutral export graph is statically audited for Node-only imports | P2 | Keep WebExtension-compatible contracts and add browser adapters incrementally |
|
|
@@ -59,6 +59,7 @@ The first code slice targeted the P0 rows only. It now contains:
|
|
|
59
59
|
6. A Chrome MV3 service worker that rehydrates state and routes messages.
|
|
60
60
|
7. A narrow content script that reports document metadata and visible text through the bridge.
|
|
61
61
|
8. Deterministic tests for browser contracts without Chrome credentials or network access.
|
|
62
|
+
9. A read-only page-world bridge with token-correlated responses and bounded `pagefacts` reads.
|
|
62
63
|
|
|
63
64
|
The extension remains an adapter. The root library continues to work without a browser, without an extension and without external memory.
|
|
64
65
|
|
|
@@ -66,7 +67,7 @@ The extension remains an adapter. The root library continues to work without a b
|
|
|
66
67
|
|
|
67
68
|
Version 1.1 implements the first slice in `extension/`: `protocol.js` provides versioned serializable messages and snapshot identity; `serviceworker.js` provides browser independent routing; `worker.js` binds that router to Manifest V3 APIs; `content.js` runs the isolated page bridge; and `popup.html` with `popup.js` provides user initiated snapshot and read actions. The package exports `@wenathlan/saddle/extension`, while the root library remains usable without Chrome.
|
|
68
69
|
|
|
69
|
-
The slice is intentionally not a full autonomous browser agent. Snapshot diffing, tab and frame identity, resumable command records, optional host escalation, browser action results and multi-browser packaging remain P1 or P2 work.
|
|
70
|
+
The slice is intentionally not a full autonomous browser agent. Snapshot diffing, tab and frame identity, resumable command records, optional host escalation, browser action results and multi-browser packaging remain P1 or P2 work. The page-world bridge is deliberately read-only and cannot evaluate arbitrary page-provided commands.
|
|
70
71
|
|
|
71
72
|
## references
|
|
72
73
|
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
# Platform pipeline audit
|
|
2
2
|
|
|
3
|
-
This document records the platform facts used by the 1.8.
|
|
3
|
+
This document records the platform facts used by the 1.8.6 pipeline work and the subsequent web root migration. The workflows remain caller-configured: repository owners provide runner availability, deployment secrets and target repository names.
|
|
4
|
+
|
|
5
|
+
## repository layout contract
|
|
6
|
+
|
|
7
|
+
The repository has one package manifest and one npm lockfile at the root. The static application is rooted at `web/` without a nested `client/` or `src/` directory: `web/index.html`, `web/main.tsx`, `web/App.tsx`, `web/components/`, `web/pages/`, `web/public/` and `web/dist/` are the canonical paths. Every Pages pipeline installs from the root with `npm ci`, runs `npm run web:check`, and writes the deployable artifact to `web/dist/public`. No nested web package, pnpm lockfile or platform workflow is retained.
|
|
4
8
|
|
|
5
9
|
## verified platform facts
|
|
6
10
|
|
|
7
11
|
| Platform | Verified contract | Source |
|
|
8
12
|
| --- | --- | --- |
|
|
9
|
-
| GitHub Pages | A custom workflow uses `actions/configure-pages@v5`, uploads a static artifact with `actions/upload-pages-artifact@v4`, then deploys with `actions/deploy-pages@v4`. The deployment job needs `pages: write` and `id-token: write`, depends on the build job and uses the `github-pages` environment. | [GitHub Pages custom workflows](https://docs.github.com/en/pages/getting-started-with-github-pages/using-custom-workflows-with-github-pages) |
|
|
13
|
+
| GitHub Pages | A custom workflow uses `actions/configure-pages@v5`, derives the project base path from the Pages output or repository name, uploads a static artifact with `actions/upload-pages-artifact@v4`, then deploys from a dependent job with `actions/deploy-pages@v4`. The deployment job needs `pages: write` and `id-token: write`, depends on the build job and uses the `github-pages` environment. The repository source is configured as GitHub Actions and the current site is `https://wenathlan.github.io/saddle/`. | [GitHub Pages custom workflows](https://docs.github.com/en/pages/getting-started-with-github-pages/using-custom-workflows-with-github-pages) |
|
|
10
14
|
| Codeberg Pages | Forgejo Actions can deploy with `https://codeberg.org/git-pages/action@v2`, using `site`, `source` and the injected `${{ forge.token }}`. Publishing the repository subdomain should be restricted to the default branch. Codeberg is migrating its legacy Pages v2 flow; custom domains still have separate constraints. | [Codeberg Pages via Forgejo Actions](https://docs.codeberg.org/codeberg-pages/forgejo-actions/), [Codeberg Pages output](https://docs.codeberg.org/codeberg-pages/pushing-output/) |
|
|
11
15
|
| GitLab Pages | A job with `pages: true` publishes the default `public` directory; the job can also use a `pages` hash for a `path_prefix`. Static HTML, CSS and JavaScript are supported through GitLab CI/CD. | [GitLab Pages](https://docs.gitlab.com/user/project/pages/) |
|
|
12
16
|
| Woodpecker CI | A workflow is a serial list of container steps with `image` and `commands`; branch/event filters belong in `when`, and secrets are injected through the pipeline environment rather than committed YAML. | [Woodpecker workflow syntax](https://woodpecker-ci.org/docs/usage/workflow-syntax) |
|
package/docs/release.md
CHANGED
|
@@ -6,10 +6,10 @@ The release path is intentionally split into source validation, package validati
|
|
|
6
6
|
|
|
7
7
|
| step | owner | condition |
|
|
8
8
|
|---|---|---|
|
|
9
|
-
| package version | repository | `package.json`
|
|
9
|
+
| package version | repository | `package.json` matches the release tag, for example `1.8.7` |
|
|
10
10
|
| quality gate | GitHub Actions | `npm run pack:check` passes |
|
|
11
|
-
| tag | repository owner | tag `v1.8.
|
|
12
|
-
| GitHub release | repository owner | release `v1.8.
|
|
11
|
+
| tag | repository owner | tag `v1.8.7` points to the validated release commit |
|
|
12
|
+
| GitHub release | repository owner | release `v1.8.7` is created from the validated tag |
|
|
13
13
|
| GitHub Packages | GitHub Actions | `publishgithubnpm.yml`, `publishghcr.yml`, `publishmaven.yml`, `publishnuget.yml`, and `publishrubygems.yml` use `GITHUB_TOKEN` |
|
|
14
14
|
| public npmjs | owner-managed GitHub Actions secret | `publishnpmjs.yml` uses `NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}` and derives the version from the release tag or latest release in manual maintenance runs |
|
|
15
15
|
| extension zip | GitHub Actions | `buildextension.yml` derives the version from the release tag, validates the unpacked artifact and attaches `saddle-extension-<version>.zip` |
|
|
@@ -22,8 +22,8 @@ The npm token previously sent in chat is compromised and must not be used. GitHu
|
|
|
22
22
|
|
|
23
23
|
```text
|
|
24
24
|
npm run pack:check
|
|
25
|
-
git tag v1.8.
|
|
26
|
-
git push origin v1.8.
|
|
25
|
+
git tag v1.8.7
|
|
26
|
+
git push origin v1.8.7
|
|
27
27
|
```
|
|
28
28
|
|
|
29
29
|
The release-created event is the publication and extension-asset trigger for the release workflows. A dry-run verifies package shape and local tests, but cannot verify registry ownership, Trusted Publisher configuration, package scope authorization, package visibility or browser-store submission; those remain settings controlled by the owner.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Release assets
|
|
2
|
+
|
|
3
|
+
The Node-only release adapter creates deterministic metadata for caller-selected artifacts. It writes `SHA256SUMS`, `sbom.cdx.json` in CycloneDX 1.5 shape and `provenance.intoto.jsonl` in an in-toto statement shape. The adapter never publishes, authenticates or selects a registry.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
npm run release:assets -- \
|
|
7
|
+
--version 1.8.7 \
|
|
8
|
+
--output build/release \
|
|
9
|
+
--artifact build/saddle.tgz \
|
|
10
|
+
--build-type caller-build \
|
|
11
|
+
--builder caller-ci
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
The artifact paths are supplied by the caller and are sorted before the checksum and provenance files are written. Package dependencies are read from the root lockfile to build a compact component list. The output can be attached to a release or checked by a registry-specific workflow without adding credentials to the library.
|
|
15
|
+
|
|
16
|
+
The package also exports the adapter as `@wenathlan/saddle/release-assets`. It is intentionally Node-only because release metadata reads files and uses the Node crypto implementation; the transport-neutral root remains free of Node imports.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Security and web audit for 1.8.7
|
|
2
|
+
|
|
3
|
+
This audit records the baseline collected before remediation. The repository owner can cross-check the live GitHub view at [Saddle Security](https://github.com/wenathlan/saddle/security) and the [Dependabot alerts API](https://docs.github.com/en/rest/dependabot/alerts).
|
|
4
|
+
|
|
5
|
+
## Baseline
|
|
6
|
+
|
|
7
|
+
GitHub reported **42 open Dependabot alerts**: 2 critical, 14 high, 23 medium and 3 low. Five alerts were associated with the root `package-lock.json`; the remaining alerts were associated with the tracked `scrape/package-lock.json`. The largest groups were `undici`, `hono`, `vite`, `shell-quote`, `brace-expansion`, `postcss`, `ip-address` and `sharp` in the nested scrape manifest.
|
|
8
|
+
|
|
9
|
+
The local root `npm audit` reported 4 vulnerabilities in the current root installation: 2 moderate, 1 high and 1 critical. The root audit is a separate view from GitHub's repository-wide alert count and does not include the stale nested scrape dependency graph unless that directory is audited independently.
|
|
10
|
+
|
|
11
|
+
Code scanning returned no analysis found, and secret scanning returned that the feature is disabled. These are coverage gaps, not evidence that the repository has no code or secret findings. The remediation therefore includes enabling or documenting the appropriate GitHub security controls without fabricating a clean result.
|
|
12
|
+
|
|
13
|
+
## Web inventory
|
|
14
|
+
|
|
15
|
+
The requested directory `web/public/manos` does not exist. The actual platform directory is `web/public/__manus__`, containing `debug-collector.js`; it is a small runtime support directory rather than a product asset directory. The public visual assets are tracked under `web/public/assets/` as four WebP files.
|
|
16
|
+
|
|
17
|
+
The first path audit found root-absolute application entry and route paths, while the asset files themselves are in the correct public directory. The Pages site is served below `/saddle/`, so every asset and internal route must be resolved through the Vite base path rather than assuming `/`.
|
|
18
|
+
|
|
19
|
+
## Remediation policy
|
|
20
|
+
|
|
21
|
+
The 1.8.7 work will prioritize Node.js built-ins for new logic, update direct and transitive dependencies through the root lockfile, isolate or remove the obsolete nested scrape dependency graph when it is not part of the published engine, preserve the small `__manus__` support directory unless its script is proven unnecessary, and make web assets base-aware. A final audit will distinguish resolved advisories from external or unfixable advisories rather than hiding them.
|
package/extension/README.md
CHANGED
|
@@ -14,7 +14,7 @@ The manifest requests only `activeTab`, `scripting` and `storage`. It does not r
|
|
|
14
14
|
|
|
15
15
|
## boundaries
|
|
16
16
|
|
|
17
|
-
The content bridge runs in Chrome's isolated world. It exposes bounded page metadata, visible text, stable references and user initiated click or fill commands.
|
|
17
|
+
The content bridge runs in Chrome's isolated world. It exposes bounded page metadata, visible text, stable references and user initiated click or fill commands. Extension snapshots carry optional window, tab and frame identifiers and can produce bounded additions, removals and changed-element diffs. `pagebridge.js` runs in the page world as a narrow read-only boundary; the isolated content script requests the `pagefacts` command through a token-correlated `postMessage` channel and rejects foreign sources or timed-out responses. The page world cannot invoke extension commands, receive credentials or evaluate arbitrary extension code. The service worker forwards versioned messages, persists bounded pending command records and restores their context metadata on explicit resume. No endpoint, credential, remote script or browser profile is embedded.
|
|
18
18
|
|
|
19
19
|
`protocol.js` and `serviceworker.js` are reusable ESM contracts. `content.js` is intentionally a classic injected file because programmatic Chrome content scripts are loaded as files; it exposes a small global bridge and avoids arbitrary page JavaScript evaluation.
|
|
20
20
|
|
|
@@ -24,4 +24,4 @@ The Node-only build adapter creates an isolated unpacked artifact with the relea
|
|
|
24
24
|
|
|
25
25
|
## next slices
|
|
26
26
|
|
|
27
|
-
The next extension slices should add
|
|
27
|
+
The next extension slices should add optional host permission escalation, richer browser action results and Firefox, Edge or Safari adapter profiles. Browser providers, login profiles, captcha solvers and remote runners remain caller owned adapters.
|
package/extension/build.js
CHANGED
|
@@ -7,7 +7,7 @@ import { dirname, resolve } from "node:path";
|
|
|
7
7
|
import { fileURLToPath } from "node:url";
|
|
8
8
|
|
|
9
9
|
const rootpath = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
10
|
-
const entries = ["manifest.json", "worker.js", "serviceworker.js", "content.js", "popup.js", "popup.html", "popup.css", "protocol.js", "permissions.js"];
|
|
10
|
+
const entries = ["manifest.json", "worker.js", "serviceworker.js", "content.js", "pagebridge.js", "popup.js", "popup.html", "popup.css", "protocol.js", "permissions.js"];
|
|
11
11
|
|
|
12
12
|
function parsearguments(argumentslist) {
|
|
13
13
|
const options = {};
|