connections: owner-configured app shortcuts on the Connect fold from a library of connection templates, with placeholders, visibility, QR codes and preset support - #27
Conversation
FelineStateMachine
left a comment
There was a problem hiding this comment.
Reviewed this head locally: typecheck and all 329 existing tests pass. The two inline findings below were reproduced separately. The branch also currently conflicts with main.
| "format": "bind.ws/relay-config/2", | ||
| "template": { | ||
| "title": "Home", | ||
| "about": "Your relay as your home on nostr. Members write, anyone reads; sites, files and Git hosting on, with notes, blog, bookmarks, sites, repos and a private photo library as shortcuts." |
There was a problem hiding this comment.
[P1] The Home preset advertises private photos while enabling public media reads
This description promises a "private photo library", but the preset sets reads: "open". I reproduced applying Home, uploading an owner file, and successfully listing it through unsigned GET /list/<owner-pubkey> and downloading its contents without authentication. visibility: "owner" only hides the shortcut in /connect.json; it does not protect the underlying library. Please describe this as an owner-only shortcut to public media, or implement actual media privacy before presenting it as a private photo library.
There was a problem hiding this comment.
Reworded rather than reimplemented, in 7f882ba and 8d55310: the Home template, the photos template, the docs and the PR description now say the photo library is a shortcut only the owner sees, and that visibility hides the shortcut and nothing else, so who may fetch the files stays the relay's read rule (members reads closes the store). Media privacy per owner is a real feature and out of this PR's scope; the wording no longer promises it.
| ], | ||
| "links": [ | ||
| { "label": "Open", "href": "https://gitworkshop.dev/relay/{relay:host|enc}" }, | ||
| { "label": "Copy clone command", "copy": "git clone '{relay:web}/{user:npub}/{input:repo}.git'" }, |
There was a problem hiding this comment.
[P2] Encode and quote the repository name before building a shell command
parseConnections accepts repository input such as kid's-project, then this template interpolates it directly inside single quotes. The resulting git clone 'https://.../kid's-project.git' fails shell syntax validation. Other accepted characters can change the URL path or introduce additional shell syntax when the copied command is pasted. Build the canonical encoded repository path and apply shell-safe quoting to the resulting URL, rather than inserting the raw input into a quoted command.
There was a problem hiding this comment.
Fixed in 8d55310. An input may now name a pattern its value must match (schema, parser, docs), and the repos template keeps the repository name to ^[A-Za-z0-9][A-Za-z0-9._\-]{0,63}$, which cannot carry a quote, a slash or whitespace into the quoted command or the URL path. parseConnections refuses a value outside the pattern, so setconnections answers 400 with connections[i].inputs.repo: must match ... and a configuration import drops the entry with the same warning; the console's input carries the pattern as well. Covered in the unit and object tests.
|
UI suggestions from the three screenshots (non-blocking): The owner editor and mobile Connect view use a lot of vertical space. The current colors, icons and bold outlines can stay while the layout becomes more compact.
For URL/command fields, use a single-line scrollable value with a fixed copy button so the phone view does not split ports and commands across several lines. |
…s/ feeds the Connect fold; a template writes its links once with {relay:*}, {owner:*}, {user:*} and {input:*} placeholders the relay fills in at GET /connect.json for whoever asks, each shortcut has a visibility (public, auth, members, owner), and the owner's list is the connections section of the configuration document, so presets carry shortcuts too
…son as tiles with a QR reveal, signed for whoever is signed in so their own links fill in, and a tenth tab, Connect, edits the list from the library with a title, who sees it, the template's inputs and the order
…rules, quiet names none, default leaves them alone like the features, and home is one name with sites, files and Git on and notes, blog, bookmarks, sites, repos, a private photo library, find-me and group one click away
…aimed relay as their visibility and the library say, setconnections refuses what does not fit and logs what it saved, the list travels with configurations and presets, and the exposure walk knocks on /connect.json
…uns a snippet before the shot with --eval, so the owner's console and an open fold are in the picture
… format, the placeholders, the owner's list and the door, and the user docs, the HTTP reference, the methods list, the README and STYLE say what the Connect fold and tab now do
… repo name keeps to letters, digits, dot, dash and underscore since it lands inside a quoted shell command and a URL path; no template carries the relay URL as a copy text, since the fold has one copy control of its own; photos says the read rule, not the shortcut, decides who sees the files
…er sees, since visibility hides the shortcut and nothing else and anyone reads a home relay, files included
… two to a row, each with one Open, a compact copy and QR control and More for the rest, folds the doors, the bridge and the Git example under Connection details, scrolls a URL or command on one line beside a fixed copy button, and the Connect tab is a compact row per shortcut with Edit opening one row's title and inputs and Save at the top lit while the list is dirty
…tconnections with the reason, an unclaimed relay drops a shortcut whose every link names the owner, and no default carries the relay URL as a copy text
… the shortcut and not what it leads to, an input may name a pattern, and the pictures are the reworked fold, tab and phone view
a13c1c9 to
8198734
Compare
|
Rebased onto main (the Git capacity work and ntig 0.6.0) and reworked the UI along the lines of the suggestions, in 7b7e2c1; the screenshots in the description are re-rendered from it.
|
…ow the list-history table, which had been added above it without one
|
The Data tab's storage bar was flush against the list-history table (the block above it was added later without a margin); fixed in a75f178, the bar now keeps a block's distance. |
What this changes
The Connect fold on a relay's page was a static sampling of nostr clients. It is now owner-configured, the way an "my apps" launcher is: a library of connection templates (
connection-templates/NN-name.jsonc, one app shortcut each) feeds a quick-configuration tab, the owner picks which shortcuts show, in what order, and who sees each, and every shortcut can reveal a QR code for a phone.A template writes its links once with placeholders the relay fills in for whoever is looking:
{relay:url},{relay:host},{relay:web},{relay:name},{relay:domain},{relay:npub},{relay:nprofile},{relay:naddr},{owner:npub},{owner:nprofile},{user:npub},{user:nprofile},{input:<name>}, with an optional|encsuffix for query strings. So one good template works on any relay.Each shortcut has a visibility:
public,auth(anyone signed in),members, orowner. Visibility hides the shortcut and nothing else: who may read the events and files a shortcut leads to stays the relay's read rule, so a photo library shortcut can be the owner's alone while the notes feed is public, and on a relay anyone reads the files are still anyone's to fetch. A visitor sees the public shortcuts; signing in on the page sends a NIP-98 signature toGET /connect.json, which then answers with what that key may see and fills the{user:*}links with the viewer's own key.The list travels with the configuration document as a top-level
connectionssection (export, import, dry-run plan), so relay templates carry it too: the seed relay templates now set the shortcuts that match their rules, and a new Home template is the enriched one-click setup (members write, anyone reads, sites, files and Git on, with notes, blog, bookmarks, sites, repos and a photo library shortcut only the owner sees).An input whose value lands in a URL path or a shell command names a
patternthe owner's value must match;reposkeeps its repository name to letters, digits, dot, dash and underscore, andsetconnectionsrefuses a value that does not match with the reason.Screenshots
The Connect fold as the owner, on a relay with the Home template applied (desktop): the relay URL first, one Open per tile with a compact copy and QR control and More for the rest, and the doors, bridge and Git example folded under Connection details:
The Connect tab in the owner's console: one compact row per shortcut (who sees it, Edit, move, remove), the row being edited open for its title and inputs, Save at the top lit while there is something unsaved, then the library:
The fold at a phone width:
Connection template library, seed list
nostr:[A-Za-z0-9._-])https://<npub>.<domain>, and the nsyte publish commandURL patterns were verified against each app's source or the console's existing links; each file's comment says where. Where no verified deep link exists, the template hands over with a
nostr:URI or the app's front page plus a copy link. No template carries a "Copy relay URL" link: the fold has one relay URL copy control at the top. The catalog isconnection-templates/README.md.Relay template changes
15-home.jsonc)Surface
src/connections.ts: the library's parser (also run by the build check), placeholder resolution, visibility,GET /connect.json.connection-template.schema.json, served at the apex like the relay-config schema;relay-config.schema.jsongainsconnections.listconnectiontemplates,listconnections,setconnections;listpresetscarries a preset's shortcuts.scripts/build/build-connections.mjsfolds the folder intosrc/gen/connections.ts;scripts/check/check-connections.mjschecks every file against the schema and the relay's parser; both run innpm run typecheck, and a file without a README row fails the build.npm run dev:shotgains--nostr(sign in as the dev key) and--eval(run a snippet before the shot); the screenshots above come from it.docs/17-connection-templates.md(developer), plus the Connect sections in00,01,04,12,13,14, README and STYLE.Tests
test/unit/connections.test.ts:fill,parseConnectionTemplate,parseConnections, the library's invariants.test/object/connections.test.ts: the door for a visitor, a signed viewer, an unclaimed relay; visibility per key; owner overrides and inputs; feature gating;{user:*}handling; defaults, empty list and order;setconnectionsrefusals, roles and the moderation log; configuration round trip with plan summaries; presets.test/object/exposure.test.tswalks/connect.jsonas a stranger and a signed-in non-member, with a members-only and an owner-only shortcut in the fixture.npm run typecheckpasses (tsc, the generated-file staleness checks for the signer, console, templates and connections, the console start check, the celld check, every connection template against the schema and the relay's parser, every relay template) andnpm testpasses: 62 files, 350 tests, on the branch rebased onto main (which brought the Git capacity work and ntig 0.6.0).