Commit graph

26 commits

Author SHA1 Message Date
lichenblankie
c4764934fe Redesign subscriptions page with card layout
Replace cramped table layout with card-based design that works
better in narrow viewports and across different themes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-05 05:06:10 +00:00
lichenblankie
69876f2275 Set share_instance = No for reliable mesh announces
With share_instance = Yes, announces weren't being sent over TCP
in Docker environments. Setting it to No ensures each TinyWeb
instance manages its own Reticulum interfaces directly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-05 05:06:10 +00:00
lichenblankie
e7ffcc179e Add delay before announce to ensure TCP interface is ready
The announce was firing before the TCP transport connection was fully
established, causing Docker instances to never announce over the mesh.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-05 05:06:10 +00:00
lichenblankie
e4c754f234 Add default internet transport node for zero-config mesh connectivity
New TinyWeb instances now auto-connect to reticulum.derickphan.com:4242
so users get internet mesh connectivity out of the box without any
manual Reticulum configuration. Env var overrides still supported.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-05 05:06:10 +00:00
lichenblankie
170de2ae9b Add entrypoint script for configurable Reticulum networking in Docker
Replaces static CMD with an entrypoint that generates RNS config from
environment variables (RNS_TCP_HOST/PORT), enabling TCP transport for
environments without LAN auto-discovery (e.g. Docker on macOS).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-05 05:06:10 +00:00
lichenblankie
5369922001 Add Dockerfile and Docker Compose for one-command setup
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-05 05:06:10 +00:00
lichenblankie
eda86d8551 Add WAL mode, connection pooling, pagination, and delta sync
WAL + pooling:
- Enable WAL journal mode for concurrent read/write support
- Add connection pool (size 4) with return_db() to reuse connections
  instead of opening/closing on every request

Pagination:
- Search results, /pages, and /tags/<name> now paginate at 50 per page
- Prev/next navigation links appear when results exceed one page

Delta sync:
- Pages table gains last_modified timestamp, set on insert/update
- /api/sites accepts ?since= param to return only changed pages
- Subscription sync uses last_sync timestamp for incremental fetches
- Remote pages upserted instead of delete-all/re-insert
- Full sync includes all_urls list for detecting remote deletions

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-05 05:06:10 +00:00
lichenblankie
00d425bc43 Normalize URLs to prevent duplicate indexing
clean_url() now canonicalizes: http→https, strips www., removes
trailing slashes, drops default ports, and sorts query params.
Prevents the same page from being indexed multiple times under
different URL variations.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-05 05:06:10 +00:00
lichenblankie
c7cc53783b Add README with setup, usage, architecture, and security docs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-05 05:06:10 +00:00
lichenblankie
cc997375fd Fix index_url using wrong page_id after upsert
lastrowid returns 0 when ON CONFLICT DO UPDATE fires on an existing
row, causing links to not be cleaned up or associated correctly on
re-index. Now fetches the actual row ID with a SELECT after upsert.
Also adds try/finally for connection safety.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-05 05:06:10 +00:00
lichenblankie
e4fafe5187 Fix SSRF redirect bypass, identity permissions, error leakage, and DB connection leaks
- SSRF: disable automatic redirects, manually follow up to 5 hops with
  IP re-validation at each step to prevent redirect-to-localhost bypass
- Identity file: enforce 0600 permissions on tinyweb_identity at load
  and creation to prevent other users from reading the private key
- Error messages: replace raw exception strings with generic messages
  to avoid leaking internal paths/hostnames to the UI
- DB connections: wrap all get_db() usage in try/finally to guarantee
  close() even when handlers throw mid-operation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-05 05:06:10 +00:00
lichenblankie
d101901361 Harden security: bookmark auth, CSP headers, per-session CSRF, and more
- Bookmark endpoint now requires a secret token (stored in settings)
- Style reset moved from GET to POST with CSRF protection
- Open redirect prevention in _redirect() helper
- Import capped at 100 URLs to prevent abuse
- page_tags cleaned up on delete + PRAGMA foreign_keys enabled
- CSP, X-Frame-Options, X-Content-Type-Options on all responses
- CSRF tokens now per-session via double-submit cookie pattern
- Tag names URL-decoded for special characters
- Gateway forwards cookies in request data

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-05 05:06:10 +00:00
lichenblankie
28ba41feb5 Add security hardening: CSRF, SSRF, FTS5, and DELETE via POST
- CSRF: Generate random token at startup, include as hidden field in
  all 11 POST forms, validate at top of POST dispatch (returns 403)
- SSRF: Block private/internal IP ranges (127/8, 10/8, 172.16/12,
  192.168/16, 169.254/16, ::1, fc00::/7) by resolving hostname before
  fetch. Remove verify=False from requests.get().
- DELETE: Change /delete/<id> from GET (instant delete) to GET
  (confirmation page) + POST (actual delete) to prevent accidental
  deletion from prefetchers/crawlers.
- FTS5: Wrap search input in double quotes to neutralize FTS5
  operators (AND, OR, NOT, *, column:). Add try/except fallback.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-05 05:06:10 +00:00
lichenblankie
7b0e56bd1d Add themes folder with kodama template and gitignore index.db
Save the custom kodama template to themes/kodama.html so it's
version-controlled as a file rather than only living in the database.
Stop tracking index.db since it's runtime data, not source code.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-05 05:06:10 +00:00
lichenblankie
37f0d42aac Add kodama tree spirit overlay and clean up orphaned remote pages
Add animated kodama (tree spirits from Princess Mononoke) to the
custom template as a canvas overlay. Each spirit has unique organic
proportions: rock-like blob head shapes, varied eye spacing/size,
optional mouths and arms, and a soft luminous glow. They fade in/out,
bob gently, and occasionally rattle their heads.

Also removed 3 orphaned remote_pages rows from deleted subscriptions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-05 05:06:10 +00:00
lichenblankie
5e02b751c2 Add custom HTML template editor and clean up UI
- Replace CSS-only customization with full HTML template editing
- Users edit the entire page wrapper with {{content}} placeholder
- Add /style?reset escape hatch to recover from broken templates
- Move nav links to template, remove redundant nav from search page
- Delete remote pages when unsubscribing from an instance

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-05 05:06:10 +00:00
lichenblankie
62a0bd54d5 Add CLAUDE.md with project architecture and conventions
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-05 05:06:10 +00:00
lichenblankie
b495bd9e79 Fix about page showing stale tag count after tag removal
Count tags from page_tags instead of the tags table, which retains
orphaned rows when tags are removed from pages.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-05 05:06:10 +00:00
lichenblankie
ab8cb2b636 Bind HTTP server to 0.0.0.0 for remote access
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-05 05:06:10 +00:00
lichenblankie
b2a098a047 Add /about landing page with slow web philosophy
Shows instance stats, destination hash for subscribing, and explains
the slow web movement and how TinyWeb works. Destination hash is
stored in settings on startup so the about page can display it.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-05 05:06:10 +00:00
lichenblankie
11b3172942 Strip tracking params from URLs and add tags/collections
URLs are cleaned of tracking parameters (utm_*, fbclid, gclid, etc.)
before indexing. Tags can be added when saving or editing pages,
browsed at /tags, and are included in search results. Tags are shared
via /api/sites and preserved when syncing/importing from subscriptions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-05 05:06:10 +00:00
lichenblankie
baf86a9d3a Single-command startup and fix bookmarklet
app.py now auto-starts the gateway HTTP server in a daemon thread,
so users only need `python app.py` to get everything running. The
gateway calls dispatch_request directly when co-located (local mode)
instead of trying to establish an RNS link to itself. Bookmarklet
hardcoded to localhost:8080. gateway.py still works standalone for
connecting to remote instances.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-05 05:06:10 +00:00
lichenblankie
ea6bced1a3 Add Reticulum-native subscriptions and sync-based distributed search
- Subscriptions now use Reticulum destination hashes instead of HTTP URLs
- All subscription syncing happens over encrypted RNS links (rns_client.py)
- Add remote_pages table for synced content from subscriptions
- Search results now include pages from synced subscriptions, grouped by source
- Remove HTTP dependency from subscription handlers

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-05 05:06:10 +00:00
lichenblankie
b6086073a7 Migrate TinyWeb to Reticulum mesh network
Replace HTTP server with Reticulum-native architecture. The server
now speaks only Reticulum, with a client-side gateway providing
browser access by translating HTTP to/from RNS requests.

- Extract db layer (db.py), templates (templates.py), handlers (handlers.py)
- app.py is now the RNS server with persistent identity and destination
- gateway.py bridges HTTP on localhost:8080 to RNS link requests
- Add rns dependency, add .gitignore

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-05 05:06:10 +00:00
lichenblankie
d68ad5e198 Bind to 0.0.0.0 and use dynamic Host header for bookmarklet
Makes the server accessible from other devices on the network
instead of only localhost. The bookmarklet now uses the Host header
from the request so it works regardless of how the server is accessed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-05 05:06:10 +00:00
lichenblankie
371e7fa30e first commit 2026-06-05 05:06:10 +00:00