Commit Graph
11 Commits
Author SHA1 Message Date
sneak a0b315c912 Event log: a double- or triple-click on an event's ID leaves it as it was
check / check (push) Successful in 3m13s
The first click of a double- or triple-click comes before its selection and
toggled the event. A later click of it that finds text selected now puts the
event back as it was before the first click. The browser test checks this
with a triple-click on the ID, checks the caret and the row's aria-expanded
both while the event is expanded and while it is collapsed, and reaches the
row with Tab from the page's Back link before pressing Enter and Space. The
event log's checks are split in three to stay within the length limit.

Model: opus-5-5
2026-10-02 21:23:21 +00:00
clawbot 7402339afb Event log: an event's ID can be selected without toggling it (closes #348)
An event's row in the event log was a button element, whose text a browser
does not let be selected, and a drag over the event's ID toggled the event.
The row is now an element with the button role: focusable, toggled by Enter
and Space, and saying whether it is expanded. A click that ends a text
selection leaves the event as it is. The browser test now also clicks the
row's caret, selects the ID with the mouse, and uses the keyboard.

Model: opus-5-5
2026-10-02 21:23:21 +00:00
clawbot da75950e91 Targets section: one Add, then a target type and Next, then that type's fields (closes #370)
check / check (push) Successful in 3m18s
The targets section of the webhook page showed its add form open with every field, a URL included for types that use none. It now lists only its targets until "+ Add" is clicked; "+ Add" shows a choice of target type with Next and Cancel on one row, and Next shows the name and only that type's fields. The database and log types show no URL field and the server stores none for them; the slack form gains its retry field. A refused target brings the page back with the form open on its type, the values entered and the reason, and Cancel empties it. An encoding failure stays a logged 500. Target validation returns its message, so the new-webhook page can reuse it.

Model: opus-5-5
2026-10-02 22:24:38 +02:00
clawbot 719d7013ee Give each event its own page and show bodies the same everywhere (closes #369)
check / check (push) Successful in 3m17s
Each event now has its own page at /hook/ID/events/EVENTID, behind the login, showing its details, its whole body and every delivery; a resubmitted copy links to its original's page. The recent events on the webhook page link there and expand to show their bodies, only the newest expanded on load. One renderer and one template show a body the same way in the recent events, the event log and the event's page: whole up to 32 KiB, cut there in the two lists with links to the event's page and the download; JSON pretty-printed unless that would grow it past four times plus 1 KiB; over 200 lines in a scrolling box; a body holding NUL or control characters treated as binary and never dumped raw.

Model: opus-5-5
2026-10-02 22:00:42 +02:00
clawbot 0f5f6ba6bf Let an entrypoint's description be edited in place (closes #392)
check / check (push) Successful in 3m19s
An entrypoint's description was set when it was added and could never change, so renaming one meant deleting it and adding a new one with a new URL every sender had to be given again. Each entrypoint on the webhook page now has an Edit button, in the shared secondary style, that opens its description in place with Save and Cancel and keeps its URL. The save goes through the same login, CSRF and ownership checks as the other entrypoint actions; an empty description shows as "Entrypoint". Activate and deactivate now write only the active column, so they cannot undo an edit. Tests cover each, through the router and the browser.

Model: opus-5-5
2026-10-02 21:32:43 +02:00
clawbot e8379272ae Load Alpine's CSP build so the UI's directives run (closes #371)
check / check (push) Successful in 3m27s
Every page's Content-Security-Policy forbids eval, which the standard Alpine.js build needs, so no directive ran in a browser: both add forms on the webhook page showed open, and events in the event log could not be collapsed. The UI now loads Alpine's CSP build (@alpinejs/csp 3.14.9 in 3p/); the policy is unchanged. Each directive names a property or method of a component registered in static/js/app.js (collapsible, targetForm), and each card holds its own x-data. A browser test, built only with the browser tag, loads the webhook page and the event log under the real headers; make test-browser runs it in Docker. New test-only dependency chromedp, which raises golang.org/x/sys to 0.47.0.

Model: opus-5-5
2026-10-02 16:09:03 +02:00
clawbot c378690977 Fetch and verify Alpine at build time instead of committing it (closes #145)
check / check (push) Successful in 2m58s
static/js/alpine.min.js was a committed minified bundle, which
REPO_POLICIES forbids, referenced by no content hash at all. A minified
blob is unreviewable, which is the shape a supply-chain compromise
takes.

script/fetch-assets now downloads Alpine 3.14.9 from the npm registry
and verifies sha256 on both the tarball and the extracted file, and
static/vendor_test.go re-hashes the bytes go:embed actually placed in
the binary. The shipped bytes are byte-identical to the blob that was
committed, so the served asset does not change.

Independently reviewed. Five negative controls reproduced by the
reviewer: flipped expected hash, repointed URL, post-fetch tampering,
asset absent, and manifest inconsistencies — each fails closed with
static/js/ left clean. Registry hashes confirmed against the pins, and
the runtime image was built, run and curled to confirm the asset is
still served and the login page still loads it.

Known gap, filed separately: static/static.go embeds the js directory
rather than named files, so a missing fetched asset is not a compile
error on ungated local build paths. Every gated path fails loudly, so
the release artifact is unaffected.
2026-08-17 23:12:17 +02:00
clawbot 0e397b3174 Correct release-blocking documentation inaccuracies (closes #141)
check / check (push) Superseded by a newer commit; never tested
The README env table was missing RETENTION_SWEEP_INTERVAL, TODO.md omitted five landed units, and three passages sold manual redelivery in the present tense when nothing implements it. The same false claim was corrected in the doc comment on failUnretryableRetry, which was its source text. Also removes a console.log from the shipped static asset.
2026-08-12 13:15:04 +02:00
clawbot aab448b076 Clarify web UI terminology, copy, and the entrypoint URL (closes #57)
check / check (push) Successful in 4s
Unifies user-visible copy on "Webhook" (routes and URLs unchanged), drops
the placeholder Profile settings section, and adds a copy-to-clipboard
affordance for the entrypoint URL as progressive enhancement — the button
stays hidden unless both the target element and the Clipboard API resolve,
so no dead control appears without JavaScript and the URL stays selectable.

Retention copy now matches what the code does: deletion is permanent, 0
retains forever, and a blank field means the default on create or the
current value on edit. The permanent-deletion sentence is suppressed for a
retain-forever webhook, which the reaper exempts before computing a cutoff.

Template tests gained a render-completed assertion. Without it, a page that
aborted mid-render still satisfied assertions matching the already-flushed
prefix, because renderTemplate streams to the ResponseWriter (#123).
2026-08-11 15:42:08 +02:00
clawbotanduser 011ec270c2 Replace Bootstrap with Tailwind CSS + Alpine.js (#14)
check / check (push) Has been cancelled
## Summary

Replaces Bootstrap CSS/JS framework with Tailwind CSS v4 + Alpine.js, matching the µPaaS UI pattern.

## Changes

- **Removed Bootstrap** — all Bootstrap CSS/JS references removed from templates
- **Added Tailwind CSS v4** — `static/css/input.css` with Material Design inspired theme, compiled to `static/css/tailwind.css`
- **Added Alpine.js 3.14.9** — vendored as `static/js/alpine.min.js` for reactive UI components
- **Rewrote all templates** to use Tailwind utility classes:
  - `base.html` — new layout structure with footer, matches µPaaS pattern
  - `htmlheader.html` — Tailwind CSS link, `[x-cloak]` style
  - `navbar.html` — Alpine.js mobile menu toggle, responsive design
  - `index.html` — card-based dashboard with Tailwind classes
  - `login.html` — centered login form with Material Design styling
  - `profile.html` — clean profile layout
- **Added `make css` target** — compiles Tailwind CSS using standalone CLI
- **Component classes** in `input.css` — reusable `.btn-primary`, `.card`, `.input`, `.alert-error` etc.

## Testing

- `make fmt` ✅
- `make check` (fmt-check, lint, test, build) ✅
- `docker build .` ✅

closes #4

Co-authored-by: user <user@Mac.lan guest wan>
Reviewed-on: #14
Co-authored-by: clawbot <clawbot@noreply.example.org>
Co-committed-by: clawbot <clawbot@noreply.example.org>
2026-03-02 00:42:29 +01:00
sneak 1244f3e2d5 initial 2026-03-01 22:52:08 +07:00