Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion llms-full.txt
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ Text version of the interactive map: This map needs JavaScript.

### Facts

- Built by: Seth Carlson and Mateo Robles
- Built by: SyberLabs
- Technology: TypeScript, React, Vinext, Cloudflare Workers, D1, Drizzle ORM, Chrome extension (Manifest V3), Playwright
- Boundary: Relay prepares and tracks application materials. It does not submit employer forms, host an MCP connection, or sync accounts in the background.
- Source: [github.com/SyberLabs/relay](https://github.com/SyberLabs/relay)
Expand Down
2 changes: 1 addition & 1 deletion mateo/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ <h1 id="portfolio-title">Mateo Robles.<em>Software &amp; Product Engineer.</em><
<figure class="portfolio-demo"><video controls playsinline preload="none" poster="/mateo/demos/rise-playback.jpg" width="1280" height="720" aria-label="RISE application: text pacing, graphics and playback"><source src="/mateo/demos/rise-playback.mp4" type="video/mp4"><a href="/mateo/demos/rise-playback.mp4">Download the RISE demonstration</a></video><figcaption>RISE / A captured demonstration of the reading and playback interface.</figcaption></figure>
<div class="portfolio-decisions">
<section><h3>What I contributed</h3><p>RISE lets readers experience text as a paced stream or a page, with sound and visuals. I led core development of text pacing and playback, moving graphics, browser audio, video export and automated tests.</p></section>
<section><h3>Where my work fits</h3><p>RISE is a team project. I collaborated with Seth Carlson and other contributors from the early application through later shared development. The recording above shows the reading and playback interface.</p></section>
<section><h3>Where my work fits</h3><p>RISE is a team project. I collaborated with other contributors from the early application through later shared development. The recording above shows the reading and playback interface.</p></section>
</div>
<aside class="portfolio-proof" aria-label="RISE contribution example"><p>An example change, PR #643: a second voice under the same playback clock. Character timestamps from the speech service become word marks, playback runs through Web Audio, and the reader’s key stays in page memory. It adds 118 unit tests.</p><a href="https://github.com/SyberLabs/RISE/pull/643">Read PR #643 ↗</a></aside>
<div class="sy-actions"><a class="sy-btn sy-btn--solid" href="https://rise.syberlabs.io/">Open RISE ↗</a><a href="/projects/rise/">RISE case study</a><a href="https://github.com/SyberLabs/RISE/blob/b5115d77e9d5b76b17f6204c6c504988df683b0d/README.md">Project development credits ↗</a></div>
Expand Down
4 changes: 2 additions & 2 deletions migrations/0001_accounts.sql
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ CREATE TRIGGER role_perms_admin_keeps_all BEFORE DELETE ON role_permissions
CREATE TABLE user_roles (
user_id TEXT NOT NULL REFERENCES users(id),
role_id TEXT NOT NULL REFERENCES roles(id) ON DELETE CASCADE,
granted_by TEXT REFERENCES users(id), -- NULL = bootstrap or break-glass, from Seth's terminal
granted_by TEXT REFERENCES users(id), -- NULL = bootstrap or break-glass, from the owner's terminal
granted_at INTEGER NOT NULL,
PRIMARY KEY (user_id, role_id)
);
Expand Down Expand Up @@ -109,7 +109,7 @@ CREATE TABLE invites (
CREATE TABLE audit_events (
id INTEGER PRIMARY KEY AUTOINCREMENT,
at INTEGER NOT NULL,
actor_user_id TEXT, -- NULL = bootstrap, from Seth's terminal
actor_user_id TEXT, -- NULL = bootstrap, from the owner's terminal
action TEXT NOT NULL, -- signin.ok invite.create invite.revoke invite.redeem
-- role.grant role.revoke role.create role.perms
-- user.disable user.enable identity.remove
Expand Down
2 changes: 1 addition & 1 deletion projects/site-data.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions scripts/account-nav.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ test('browser back refreshes signed-out HTML after login and validates sign-out
const f = fixture(); account(f.doc);
f.requests[0].resolve(response(401)); await settle();
const back = f.win.dispatch('pageshow');
f.requests[1].resolve(signedIn('@seth')); await back;
f.requests[1].resolve(signedIn('@octocat')); await back;
assert.equal(f.nodes['sy-account-member'].hidden, false);
const focus = f.win.dispatch('focus');
f.requests[2].resolve(response(401)); await focus;
Expand All @@ -101,7 +101,7 @@ test('visibility refresh waits until visible and old requests cannot overwrite n

test('transient server failures, malformed replies and timeout preserve validated state', async () => {
const f = fixture(); const refresh = account(f.doc);
f.requests[0].resolve(signedIn('@seth')); await settle();
f.requests[0].resolve(signedIn('@octocat')); await settle();
for (const result of [response(503), response(200, { version: 1, user: null })]) {
const pending = refresh(); f.requests.at(-1).resolve(result); await pending;
assert.equal(f.nodes['sy-account-member'].hidden, false);
Expand Down
8 changes: 4 additions & 4 deletions server/CONTRACT.md
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ and `helpers.js` (`makeEnv`, `seedRole`, `seedUser`, `seedSession`, `signIn`, `c
`providerLabel(p)`. `page()` puts its own " · SyberLabs staff" after `title`; `alert(kind, html)` kinds are
`neutral | success | warning | danger`.
- `forbidden.js` re-exports `notFoundHtml`, `errorHtml`, `unavailableHtml`, `CSRF_COPY` from `views/error.js`.
- `confirm.js` exports `confirmed(ctx)`, `actingAs(user)` ("You, Seth via GitHub," escaped, trailing comma) and
- `confirm.js` exports `confirmed(ctx)`, `actingAs(user)` ("You, @octocat (GitHub)," escaped, trailing comma) and
`confirmHtml(ctx, {title, lines, action, fields, submitLabel, cancel = '/admin/', section})` -> string.
- Sign-in page: one GitHub form, and the `e=` copy names GitHub (no `?p=` until Packet 5 adds a second provider). Its forms send `switch=1` (no `prompt` field), and `login_hint` on a Google invite. Copy follows RFC 3.4;
the no-keys empty state says "Ask an admin" (no names in the repo).
Expand Down Expand Up @@ -230,14 +230,14 @@ and `helpers.js` (`makeEnv`, `seedRole`, `seedUser`, `seedSession`, `signIn`, `c
`change_entries.created_by`/`updated_by`/`updated_at`/`deleted_at`; `audit_dedupe` and the 90-day `signin.denied`
retention tier are gone. `change_entries_order` replaces the partial index.
- `/api/me`, `/api/admin/changes` and `/api/*` in `_routes.json` are gone (RFC R1-8); every error is HTML.
- Bootstrap writes users, identities and grants directly from Seth's terminal (RFC 8.4.8); its audit action is
- Bootstrap writes users, identities and grants directly from the owner's terminal (RFC 8.4.8); its audit action is
`bootstrap`.
- **review round 2:**
- **Spec target.** This branch implements RFC-0002 as of `88e25a9` (red-team round 2). Round 3 (`e4f92b8`) deletes
invites (`invites` table, `login_hint`, case b, redemption batch, invite revoke, open-invites list, `welcome=1`) for
`POST /admin/people/add`, drops `users.display_name` and the seeded `viewer`, makes `/auth/signin` never redirect,
makes `POST /auth/signout` PUBLIC and splits a CI function job. Those are not adopted here: whether this branch
tracks round 3 is Seth's call. Reviews should not flag that drift until he decides. Round 3 items adopted one by one
tracks round 3 is the owner's call. Reviews should not flag that drift until the owner decides. Round 3 items adopted one by one
are cited in code (`enableUser` confirm).
- Confirm pages also cover deleting a What changed entry (RFC 2.4, 3.5, test 15) and turning on an account that holds
`role_admin` (RFC `e4f92b8` 2.4, 8.2, test 19).
Expand Down Expand Up @@ -301,7 +301,7 @@ implemented, with the reason:
this task keeps the CI guards and their `if` form. Packet 1b's canary guard and the removal of #84's `rm -f` are done.
- **Headers (8.2).** `X-Frame-Options`, `Permissions-Policy` and `Cross-Origin-Opener-Policy` stay: the RFC says they
add nothing, not that they harm. `form-action` names only GitHub until Packet 5 adds Google.
- **Names in copy (3.3, 3.4: "Ask Seth or Mateo").** The copy says "Ask an admin": no names in the repo.
- **Names in copy (3.3, 3.4).** The copy says "Ask an admin": no names in the repo.
- **`id:users.manage` label (2.4).** The permission now includes removing sign-in methods; the existing live schema already supports Packet 5 without new identity columns.
- **Two RFC conflicts, settled for the copy table in 3.4.** Test 4 expects `e=refused` for `error=server_error`, but
3.4 has no such code and maps every non-`access_denied` error to `provider`; the code uses `e=provider&p=github`.
Expand Down
2 changes: 1 addition & 1 deletion server/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export const ROUTES = [
['GET /admin/roles', 'id:users.read', rolesPage],
['POST /admin/roles', 'id:roles.manage', saveRole], // RFC-0002 8.2: non-privileged keys only
['GET /admin/audit', 'id:audit.read', auditPage],
// Packet 5. Removing a sign-in method has no page in v1: it is Seth's runbook step (RFC-0002 2.5, 8.4.9).
// Packet 5. Removing a sign-in method has no page in v1: it is the owner's runbook step (RFC-0002 2.5, 8.4.9).
['POST /admin/account/add-google', SIGNED_IN, addGoogle, { provider: 'google' }], // session under 10 min
];

Expand Down
4 changes: 2 additions & 2 deletions server/test/people.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,14 @@ test('people page: one list item per person (no table); readers get no actions;

test('case 21: granting admin needs the confirm page, which names the acting identity; confirm=1 grants', async () => {
const env = makeEnv();
const admin = await signIn(env.DB, { roles: ['role_admin'], login: 'seth-test' });
const admin = await signIn(env.DB, { roles: ['role_admin'], login: 'admin-test' });
const target = await signIn(env.DB, { roles: ['role_viewer'], login: 'mateo-test' });
const before = env.DB.totalChanges();
let res = await call(env, '/admin/people/roles/grant', { cookie: admin.cookie, form: { user: target.userId, role: 'role_admin' } });
assert.equal(res.status, 200);
const page = await res.text();
// RFC-0002 3.5: the acting identity, then the target as "@login (GitHub id N)".
assert.match(page, new RegExp(`You, @seth-test \\(GitHub\\), are granting <strong>admin</strong> to @mateo-test \\(GitHub id ${target.subject}\\)\\.`));
assert.match(page, new RegExp(`You, @admin-test \\(GitHub\\), are granting <strong>admin</strong> to @mateo-test \\(GitHub id ${target.subject}\\)\\.`));
assert.match(page, /Admin can add people, grant and revoke roles, turn accounts off and on, and create roles\./);
assert.match(page, /href="\/admin\/people">Cancel<\/a>/);
assert.match(page, /name="confirm" value="1"/);
Expand Down
14 changes: 7 additions & 7 deletions server/test/views.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,16 +76,16 @@ test('nav is filtered by permissions and always includes Launchpad, Saved things
});

test('workspace shell keeps profile and permission-filtered desktop and mobile navigation available without scripts', () => {
const html = page(ctxFor({ perms: ['site:changes.read'], user: { login: 'sdcarlson' } }), { title: 'X', body: '', section: 'changes' });
const html = page(ctxFor({ perms: ['site:changes.read'], user: { login: 'octocat' } }), { title: 'X', body: '', section: 'changes' });
assert.match(html, /<body class="workspace-app">/);
assert.match(html, /class="workspace-sidebar"/);
assert.match(html, /<details class="workspace-mobile-nav"><summary>Navigate<\/summary>/);
assert.equal((html.match(/aria-label="Workspace"/g) || []).length, 2);
assert.equal((html.match(/aria-label="Team"/g) || []).length, 2);
assert.equal((html.match(/href="\/admin\/changes" aria-current="page"/g) || []).length, 2);
assert.equal((html.match(/action="\/auth\/signout"/g) || []).length, 2);
assert.match(html, /aria-label="Profile: @sdcarlson \(GitHub\)"/);
assert.match(html, /staff-profile__label">@sdcarlson<small>GitHub<\/small>/);
assert.match(html, /aria-label="Profile: @octocat \(GitHub\)"/);
assert.match(html, /staff-profile__label">@octocat<small>GitHub<\/small>/);
assert.doesNotMatch(html, /\/admin\/people|\/admin\/roles|\/admin\/audit/);
const byId = page(ctxFor({ user: { login: null, subject: '4242' } }), { title: 'X', body: '' });
assert.match(byId, /Profile: GitHub id 4242 \(GitHub\)/);
Expand Down Expand Up @@ -355,7 +355,7 @@ test('404 and CSRF pages render in the chrome', async () => {

test('audit page: an ordered list of one-line sentences, newest first, names never hex, empty state', async () => {
const env = makeEnv();
const admin = await signIn(env.DB, { perms: ['id:audit.read'], login: 'sdcarlson' });
const admin = await signIn(env.DB, { perms: ['id:audit.read'], login: 'octocat' });
const empty = await (await call(env, '/admin/audit', { cookie: admin.cookie })).text();
assert.match(empty, /Nothing recorded yet\./);
const byId = seedUser(env.DB, { login: null, subject: '4242' });
Expand All @@ -370,10 +370,10 @@ test('audit page: an ordered list of one-line sentences, newest first, names nev
noRawXss(body);
assert.match(body, /<ol class="staff-audit">/);
assert.doesNotMatch(body, /<table/);
assert.ok(body.includes('<li><time datetime="2026-10-09T14:02:00.000Z">2026-10-09 14:02 UTC</time>, @sdcarlson turned off GitHub id 4242.</li>'));
assert.ok(body.includes('<li><time datetime="2026-10-09T14:02:00.000Z">2026-10-09 14:02 UTC</time>, @octocat turned off GitHub id 4242.</li>'));
assert.ok(body.includes('the terminal added the What changed entry "&lt;script&gt;'));
assert.ok(body.includes('@sdcarlson granted viewer to a removed account.'));
assert.ok(body.includes('@sdcarlson added GitHub id 4242 as admin.'));
assert.ok(body.includes('@octocat granted viewer to a removed account.'));
assert.ok(body.includes('@octocat added GitHub id 4242 as admin.'));
assert.ok(body.indexOf('added GitHub id 4242') < body.indexOf('turned off GitHub id 4242'), 'newest first');
assert.doesNotMatch(body, /ffffffff|203\.0\.113/, 'no hex ids, no IP prefixes');
});
Expand Down
4 changes: 2 additions & 2 deletions server/views/audit.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// /admin/audit (RFC-0002 2.6): the last 200 events, newest first, as an <ol> of one-line sentences:
// "2026-10-09 14:02 UTC, @sdcarlson turned off @x." Actor and target render from the identity join as
// "2026-10-09 14:02 UTC, @octocat turned off @x." Actor and target render from the identity join as
// @login, else "GitHub id N", else "a removed account"; a hex id is never printed. Read only.
import { esc, html } from '../http.js';
import { displayNames } from '../authz.js';
Expand Down Expand Up @@ -47,7 +47,7 @@ export async function auditPage(ctx) {
if (r.target_type === 'user' && r.target_id) ids.add(r.target_id);
}
const names = ids.size ? await displayNames(db, [...ids]) : new Map();
// A NULL actor is Seth's terminal: bootstrap or break-glass (RFC-0002 8.1).
// A NULL actor is the owner's terminal: bootstrap or break-glass (RFC-0002 8.1).
const who = id => (id ? names.get(id) || 'a removed account' : 'the terminal');

const sentence = r => {
Expand Down
2 changes: 1 addition & 1 deletion server/views/chrome.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export { identityName };
export const PROVIDER_LABEL = { github: 'GitHub', google: 'Google' };
export const providerLabel = p => PROVIDER_LABEL[p] || 'the provider';

// "@sdcarlson (GitHub)", or "you@example.com (Google)"
// "@octocat (GitHub)", or "you@example.com (Google)"
export const signedInAs = user => `${identityName(user)} (${providerLabel(user.provider)})`;

// The section nav (RFC-0002 3.3), in this order. Account is open to every session, the rest need their key.
Expand Down
2 changes: 1 addition & 1 deletion server/views/confirm.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { page, head, hidden, signedInAs } from './layout.js';
// A confirm route acts only on the second POST.
export const confirmed = ctx => ctx.form.get('confirm') === '1';

// "You, @sdcarlson (GitHub)," (escaped): the acting identity, named on every confirm page.
// "You, @octocat (GitHub)," (escaped): the acting identity, named on every confirm page.
export const actingAs = user => `You, ${esc(signedInAs(user))},`;

// lines: trusted HTML strings (callers escape every value). fields: object or [name, value] pairs.
Expand Down
4 changes: 2 additions & 2 deletions server/views/people.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ async function userById(db, id) {
// once shared a login cannot be confused (RFC-0002 3.5).
const fullName = p => (p.provider !== 'google' && p.login ? `@${p.login} (GitHub id ${p.subject})` : identityName(p));

// "Admins left after this: @sdcarlson; GitHub id N (never signed in)." (RFC-0002 2.4, 3.5)
// "Admins left after this: @octocat; GitHub id N (never signed in)." (RFC-0002 2.4, 3.5)
async function adminsLeftLine(db, userId) {
const { results } = await db.prepare(`SELECT i.provider, i.login, i.subject, i.email, ${LAST_SIGNIN} AS last_login_at
FROM admins a JOIN users u ON u.id = a.user_id LEFT JOIN identities i ON i.id = ${FIRST_IDENTITY}
Expand All @@ -60,7 +60,7 @@ async function loadPeople(db) {
return { users: users.results, identities: identities.results, grants: grants.results, roles: roles.results };
}

// "GitHub @login" or "Google you@example.com". There is no Remove button: removing a method is Seth's runbook
// "GitHub @login" or "Google you@example.com". There is no Remove button: removing a method is the owner's runbook
// step (RFC-0002 2.5, 8.4.9).
const methodLabel = i => (i.provider === 'google' ? `Google ${identityName(i)}`
: i.login ? `GitHub @${i.login}` : `GitHub id ${i.subject}`);
Expand Down
2 changes: 1 addition & 1 deletion src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ const pauseOtherVideos = event => { for (const video of document.querySelectorAl

// The lab's work, shown in the hero from the first frame, each line linked to its section below.
// Mateo's personal credentials (degree, availability) live on /mateo/, the hiring page every application links to.
// Third place confirmed by Seth Carlson (Oct 27); event and project tied together by PorchLight's README.
// Third place confirmed by SyberLabs (Oct 27); event and project tied together by PorchLight's README.
const HACKATHON = { result: 'third place', event: 'Cline, Parallel & Composio Hackathon', date: 'October 2026', href: '#porchlight' };
const WORK = [
{ label: 'GitHits', text: 'Design partnership: an A/B pilot and a GitHits client for Claude Code', href: '#work' },
Expand Down
2 changes: 1 addition & 1 deletion wrangler.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Cloudflare Pages config for syberlabs-home (auth plan 11.3, RFC-0002 8.4.3). Once this file exists it is the
# source of truth: the dashboard can no longer edit these fields. Every REPLACE_ME is filled in by Seth from
# source of truth: the dashboard can no longer edit these fields. Every REPLACE_ME is filled in by the owner from
# `wrangler d1 create` and the OAuth app pages before merge; until then a deploy fails on purpose.
# Client ids are public by nature. Secrets (APP_SECRET, *_CLIENT_SECRET) never go here.
name = "syberlabs-home"
Expand Down
Loading