diff --git a/llms-full.txt b/llms-full.txt
index 981f1ef..2f1afc7 100644
--- a/llms-full.txt
+++ b/llms-full.txt
@@ -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)
diff --git a/mateo/index.html b/mateo/index.html
index ff3cc58..b168c26 100644
--- a/mateo/index.html
+++ b/mateo/index.html
@@ -126,7 +126,7 @@
Mateo Robles.Software & Product Engineer.<
RISE / A captured demonstration of the reading and playback interface.
What I contributed
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.
-
Where my work fits
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.
+
Where my work fits
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.
diff --git a/migrations/0001_accounts.sql b/migrations/0001_accounts.sql
index a7369bd..8f8e644 100644
--- a/migrations/0001_accounts.sql
+++ b/migrations/0001_accounts.sql
@@ -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)
);
@@ -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
diff --git a/projects/site-data.js b/projects/site-data.js
index 95899d2..66eab1e 100644
--- a/projects/site-data.js
+++ b/projects/site-data.js
@@ -293,7 +293,7 @@ export const projects = [
['not yet', 'No public deployment and no customer counts, hiring outcomes or throughput improvements are claimed. Autonomous hunting is not included.'],
],
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', { label: 'github.com/SyberLabs/relay', href: 'https://github.com/SyberLabs/relay' }],
diff --git a/scripts/account-nav.test.mjs b/scripts/account-nav.test.mjs
index 4ff7187..0c61e6f 100644
--- a/scripts/account-nav.test.mjs
+++ b/scripts/account-nav.test.mjs
@@ -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;
@@ -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);
diff --git a/server/CONTRACT.md b/server/CONTRACT.md
index 3d2ed9a..120adc1 100644
--- a/server/CONTRACT.md
+++ b/server/CONTRACT.md
@@ -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).
@@ -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).
@@ -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`.
diff --git a/server/routes.js b/server/routes.js
index b4af776..079abbb 100644
--- a/server/routes.js
+++ b/server/routes.js
@@ -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
];
diff --git a/server/test/people.test.js b/server/test/people.test.js
index ed145d0..f3e1a31 100644
--- a/server/test/people.test.js
+++ b/server/test/people.test.js
@@ -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 admin to @mateo-test \\(GitHub id ${target.subject}\\)\\.`));
+ assert.match(page, new RegExp(`You, @admin-test \\(GitHub\\), are granting admin 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"/);
diff --git a/server/test/views.test.js b/server/test/views.test.js
index a9106ad..c3fdcb6 100644
--- a/server/test/views.test.js
+++ b/server/test/views.test.js
@@ -76,7 +76,7 @@ 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, //);
assert.match(html, /class="workspace-sidebar"/);
assert.match(html, /Navigate<\/summary>/);
@@ -84,8 +84,8 @@ test('workspace shell keeps profile and permission-filtered desktop and mobile n
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">@sdcarlsonGitHub<\/small>/);
+ assert.match(html, /aria-label="Profile: @octocat \(GitHub\)"/);
+ assert.match(html, /staff-profile__label">@octocatGitHub<\/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\)/);
@@ -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' });
@@ -370,10 +370,10 @@ test('audit page: an ordered list of one-line sentences, newest first, names nev
noRawXss(body);
assert.match(body, //);
assert.doesNotMatch(body, /
, @sdcarlson turned off GitHub id 4242.'));
+ assert.ok(body.includes('
, @octocat turned off GitHub id 4242.
'));
assert.ok(body.includes('the terminal added the What changed entry "<script>'));
- 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');
});
diff --git a/server/views/audit.js b/server/views/audit.js
index ca06f5d..556c54c 100644
--- a/server/views/audit.js
+++ b/server/views/audit.js
@@ -1,5 +1,5 @@
// /admin/audit (RFC-0002 2.6): the last 200 events, newest first, as an 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';
@@ -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 => {
diff --git a/server/views/chrome.js b/server/views/chrome.js
index e8399a3..32c5de1 100644
--- a/server/views/chrome.js
+++ b/server/views/chrome.js
@@ -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.
diff --git a/server/views/confirm.js b/server/views/confirm.js
index 571a031..8665665 100644
--- a/server/views/confirm.js
+++ b/server/views/confirm.js
@@ -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.
diff --git a/server/views/people.js b/server/views/people.js
index 817a774..6312f44 100644
--- a/server/views/people.js
+++ b/server/views/people.js
@@ -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}
@@ -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}`);
diff --git a/src/App.jsx b/src/App.jsx
index 150b2a2..d7d776b 100644
--- a/src/App.jsx
+++ b/src/App.jsx
@@ -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' },
diff --git a/wrangler.toml b/wrangler.toml
index 3e949a1..7e18068 100644
--- a/wrangler.toml
+++ b/wrangler.toml
@@ -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"