mirror of
https://github.com/J3vb/OwnCord.git
synced 2026-09-02 19:43:10 +03:00
refactor: re-point paths after the Client flatten (mechanical, no behaviour change)
This commit is contained in:
@@ -34,7 +34,7 @@ fault, same verdict, especially when the diff touches no Go code. Rerun the
|
||||
job (`gh run rerun --job <id>`); a job cannot be rerun while its parent run is
|
||||
still in progress.
|
||||
|
||||
## Client (from `Client/tauri-client/`)
|
||||
## Client (from `Client/`)
|
||||
|
||||
```bash
|
||||
NODE_OPTIONS=--no-experimental-webstorage npm test
|
||||
@@ -47,7 +47,7 @@ The `NODE_OPTIONS` flag is mandatory on Node 22+ — see the client CLAUDE.md.
|
||||
|
||||
`npm audit --audit-level=high` and `knip` also run in CI but are advisory.
|
||||
|
||||
## Rust (from `Client/tauri-client/src-tauri/`)
|
||||
## Rust (from `Client/src-tauri/`)
|
||||
|
||||
```bash
|
||||
cargo test
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: protocol-change
|
||||
description: Add or change a WebSocket message type in OwnCord. Use before editing docs/protocol-schema.json, Server/ws/message_types.go, or Client/tauri-client/src/lib/protocolTypes.ts.
|
||||
description: Add or change a WebSocket message type in OwnCord. Use before editing docs/protocol-schema.json, Server/ws/message_types.go, or Client/src/lib/protocolTypes.ts.
|
||||
---
|
||||
|
||||
# protocol-change
|
||||
@@ -11,7 +11,7 @@ generated from it by `Server/scripts/genprotocol/`.
|
||||
1. Edit `docs/protocol-schema.json`.
|
||||
2. Run `make protocol-generate` from `Server/`.
|
||||
3. Commit **both** outputs — `Server/ws/message_types.go` and
|
||||
`Client/tauri-client/src/lib/protocolTypes.ts`. One run regenerates the
|
||||
`Client/src/lib/protocolTypes.ts`. One run regenerates the
|
||||
pair; committing only the Go side is the usual mistake, and CI's
|
||||
`make protocol-verify` fails on either being stale.
|
||||
|
||||
@@ -20,4 +20,4 @@ shapes, not behaviour.
|
||||
|
||||
Adding a message type is not enough to make it work: a server handler must be
|
||||
registered in the `ws` V1/V2 dispatch tables, and the client needs a
|
||||
`ws.on(...)` subscription in `Client/tauri-client/src/lib/dispatcher.ts`.
|
||||
`ws.on(...)` subscription in `Client/src/lib/dispatcher.ts`.
|
||||
|
||||
@@ -46,7 +46,7 @@ export async function run({ agentStub, args = undefined, budget = undefined }) {
|
||||
export const rec = (id, over = {}) => ({
|
||||
id,
|
||||
title: `bug ${id}`,
|
||||
file: 'Client/tauri-client/src/lib/livekitE2EE.ts',
|
||||
file: 'Client/src/lib/livekitE2EE.ts',
|
||||
line: 100,
|
||||
severity: 'high',
|
||||
why: 'w',
|
||||
@@ -78,7 +78,7 @@ scenarios.f1_clusters_by_file = async () => {
|
||||
assert.equal(result.branch, 'fix/test')
|
||||
assert.equal(result.clusters.length, 2)
|
||||
const byFile = Object.fromEntries(result.clusters.map((c) => [c.file, c.ids]))
|
||||
assert.deepEqual(byFile['Client/tauri-client/src/lib/livekitE2EE.ts'], ['OC-0001', 'OC-0002'])
|
||||
assert.deepEqual(byFile['Client/src/lib/livekitE2EE.ts'], ['OC-0001', 'OC-0002'])
|
||||
assert.deepEqual(byFile['Server/ws/hub_sweep.go'], ['OC-0003'])
|
||||
}
|
||||
|
||||
@@ -580,7 +580,7 @@ scenarios.f14_disjoint_touched_paths_both_commit = async () => {
|
||||
if (opts.label.includes('livekitE2EE'))
|
||||
return {
|
||||
results: [{ id: 'OC-0001', outcome: 'fixed', testPath: 't/OC-0001.test.ts', rationale: '' }],
|
||||
touchedPaths: ['Client/tauri-client/src/lib/otherHelper.ts'],
|
||||
touchedPaths: ['Client/src/lib/otherHelper.ts'],
|
||||
}
|
||||
return {
|
||||
results: [{ id: 'OC-0003', outcome: 'fixed', testPath: 'Server/ws/hub_sweep_test.go', rationale: '' }],
|
||||
@@ -616,7 +616,7 @@ scenarios.f15_prove_prompt_names_every_touched_path = async () => {
|
||||
if (String(opts.label).startsWith('fix:'))
|
||||
return {
|
||||
results: [{ id: 'OC-0001', outcome: 'fixed', testPath: 't/OC-0001.test.ts', rationale: '' }],
|
||||
touchedPaths: ['Client/tauri-client/src/lib/sharedCrypto.ts'],
|
||||
touchedPaths: ['Client/src/lib/sharedCrypto.ts'],
|
||||
}
|
||||
if (String(opts.label).startsWith('prove:')) {
|
||||
provePromptText = prompt
|
||||
@@ -651,8 +651,8 @@ scenarios.f15_prove_prompt_names_every_touched_path = async () => {
|
||||
const FOUR_FILES = [
|
||||
rec('OC-0001'),
|
||||
rec('OC-0002', { file: 'Server/ws/hub_sweep.go' }),
|
||||
rec('OC-0003', { file: 'Client/tauri-client/src/lib/livekitSession.ts' }),
|
||||
rec('OC-0004', { file: 'Client/tauri-client/src/components/VoiceWidget.ts' }),
|
||||
rec('OC-0003', { file: 'Client/src/lib/livekitSession.ts' }),
|
||||
rec('OC-0004', { file: 'Client/src/components/VoiceWidget.ts' }),
|
||||
]
|
||||
// A fix stub that reports every id in its prompt as fixed. Ids go through a Set because rec()
|
||||
// puts each id in both `id` and `title`, so the raw matchAll yields every id twice.
|
||||
|
||||
@@ -150,7 +150,7 @@ function fixPrompt(cluster) {
|
||||
`alone, return outcome "declined" with a rationale. Do not invent a fix you do not believe in.\n` +
|
||||
` 8. If you cannot fix it for a mechanical reason (missing fixture, unclear repro), return "blocked" ` +
|
||||
`with a rationale.\n\n` +
|
||||
`Client tests run from Client/tauri-client with:\n` +
|
||||
`Client tests run from Client with:\n` +
|
||||
` NODE_OPTIONS=--no-experimental-webstorage npx vitest run <testfile>\n` +
|
||||
`Server tests run from Server with:\n` +
|
||||
` go test ./<pkg>/ -run <TestName>\n\n` +
|
||||
@@ -336,7 +336,7 @@ function provePrompt(cluster, fixedIds, testPaths, sourcePaths) {
|
||||
` Use a conventional-commit area matching the file (voice, ws, client, identity...). Do not add a ` +
|
||||
`Co-Authored-By trailer.\n` +
|
||||
` 9. Return the short sha.\n\n` +
|
||||
`Client tests run from Client/tauri-client with:\n` +
|
||||
`Client tests run from Client with:\n` +
|
||||
` NODE_OPTIONS=--no-experimental-webstorage npx vitest run <testfile>\n` +
|
||||
`Server tests run from Server with:\n` +
|
||||
` go test ./<pkg>/ -run <TestName>`
|
||||
@@ -433,7 +433,7 @@ function stacksFor(files) {
|
||||
const s = new Set()
|
||||
for (const f of files) {
|
||||
if (f.startsWith('Server/')) s.add('server')
|
||||
else if (f.startsWith('Client/tauri-client/src-tauri/')) s.add('rust')
|
||||
else if (f.startsWith('Client/src-tauri/')) s.add('rust')
|
||||
else if (f.startsWith('Client/')) s.add('client')
|
||||
}
|
||||
return [...s]
|
||||
@@ -441,7 +441,7 @@ function stacksFor(files) {
|
||||
|
||||
const GATE_COMMANDS = {
|
||||
client:
|
||||
`From Client/tauri-client:\n` +
|
||||
`From Client:\n` +
|
||||
` NODE_OPTIONS=--no-experimental-webstorage npm test\n` +
|
||||
` npm run typecheck\n` +
|
||||
` npm run lint\n` +
|
||||
@@ -456,10 +456,10 @@ const GATE_COMMANDS = {
|
||||
` make sqlc-verify protocol-verify # generated output must not be stale. If make is not on PATH, ` +
|
||||
`run the equivalent commands directly instead: ` +
|
||||
`"sqlc generate && git diff --exit-code db/dbgen" and ` +
|
||||
`"go run ./scripts/genprotocol && git diff --exit-code ws/message_types.go ../Client/tauri-client/src/lib/protocolTypes.ts" ` +
|
||||
`"go run ./scripts/genprotocol && git diff --exit-code ws/message_types.go ../Client/src/lib/protocolTypes.ts" ` +
|
||||
`- a non-empty diff in either means generated code is stale and the gate fails`,
|
||||
rust:
|
||||
`From Client/tauri-client/src-tauri:\n` +
|
||||
`From Client/src-tauri:\n` +
|
||||
` cargo test\n` +
|
||||
` cargo clippy --all-targets -- -D warnings`,
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ export function makeStub({ hunt, verify, recon = defaultRecon }) {
|
||||
}
|
||||
}
|
||||
export function defaultRecon() {
|
||||
return 'Server/ws/hub.go 12\nServer/api/user.go 9\nClient/tauri-client/src/lib/dispatcher.ts 8'
|
||||
return 'Server/ws/hub.go 12\nServer/api/user.go 9\nClient/src/lib/dispatcher.ts 8'
|
||||
}
|
||||
export const none = { findings: [] }
|
||||
export const finding = (n, over = {}) => ({
|
||||
@@ -363,7 +363,7 @@ scenarios.s_graph_missing_fallback = async () => {
|
||||
scenarios.s7_adaptive_lenses = async () => {
|
||||
const A = finding(1, { file: 'Server/ws/hub.go', line: 120, title: 'alpha race window one' })
|
||||
const B = finding(2, { file: 'Server/ws/pubsub.go', line: 60, title: 'beta subscription leak two' })
|
||||
const C = finding(3, { file: 'Client/tauri-client/src/lib/livekitE2EE.ts', line: 200, title: 'gamma epoch desync three' })
|
||||
const C = finding(3, { file: 'Client/src/lib/livekitE2EE.ts', line: 200, title: 'gamma epoch desync three' })
|
||||
const { result, calls } = await run({
|
||||
agentStub: makeStub({
|
||||
hunt: (round, key) => {
|
||||
@@ -380,7 +380,7 @@ scenarios.s7_adaptive_lenses = async () => {
|
||||
assert.equal(result.rounds[3].family, 'adaptive')
|
||||
const r4Keys = [...new Set(calls.filter((c) => /^r4:hunt:/.test(c.opts.label || '')).map((c) => c.opts.label.split(':')[2]))]
|
||||
assert.ok(r4Keys.includes('hotspot-server-ws'), `r4 keys: ${r4Keys}`)
|
||||
assert.ok(r4Keys.includes('hotspot-client-tauri-client-src-lib'), `r4 keys: ${r4Keys}`)
|
||||
assert.ok(r4Keys.includes('hotspot-client-src-lib'), `r4 keys: ${r4Keys}`)
|
||||
assert.ok(r4Keys.includes('explore-1'), `r4 keys: ${r4Keys}`)
|
||||
const hotspot = calls.find((c) => (c.opts.label || '').includes('hotspot-server-ws'))
|
||||
assert.match(hotspot.prompt, /Server\/ws\/hub\.go/)
|
||||
|
||||
@@ -87,7 +87,7 @@ const VERDICTS = {
|
||||
// ---------- rules ----------
|
||||
const RULES = `
|
||||
Repo: OwnCord, checked out at your current working directory (the repo root - do not assume any absolute
|
||||
path; run every command from there and use repo-relative paths). Go 1.26 server in Server/, Tauri v2 client in Client/tauri-client/
|
||||
path; run every command from there and use repo-relative paths). Go 1.26 server in Server/, Tauri v2 client in Client/
|
||||
(Rust in src-tauri/src/, TypeScript in src/lib/ and src/stores/).
|
||||
|
||||
You are hunting REAL BUGS: wrong behavior, not style. In scope:
|
||||
@@ -132,8 +132,8 @@ const SURFACE_LENSES = [
|
||||
key: 'voice-e2ee',
|
||||
prompt:
|
||||
`Surface: voice/video E2EE key lifecycle, spanning three languages. Files: Server/ws/handler_v2_voice*.go and ` +
|
||||
`any Server/ws/*voice*.go or *e2ee*.go; Client/tauri-client/src/lib/e2eeCrypto.ts, livekitE2EE.ts, ` +
|
||||
`livekitSession.ts, identity.ts; Client/tauri-client/src-tauri/src/tofu.rs, secret_store.rs, fallback_crypto.rs, dpapi.rs.\n\n` +
|
||||
`any Server/ws/*voice*.go or *e2ee*.go; Client/src/lib/e2eeCrypto.ts, livekitE2EE.ts, ` +
|
||||
`livekitSession.ts, identity.ts; Client/src-tauri/src/tofu.rs, secret_store.rs, fallback_crypto.rs, dpapi.rs.\n\n` +
|
||||
`Hunt specifically for: a key-rotation window where a participant can decrypt after they should be excluded; ` +
|
||||
`TOFU pin re-check that reads state captured before a rotation (time-of-check/time-of-use); a participant ` +
|
||||
`joining mid-rotation getting the wrong epoch key; key material outliving the session; an error path that ` +
|
||||
@@ -167,7 +167,7 @@ const SURFACE_LENSES = [
|
||||
{
|
||||
key: 'tauri-rust',
|
||||
prompt:
|
||||
`Surface: the Tauri Rust backend. Files: Client/tauri-client/src-tauri/src/*.rs.\n\n` +
|
||||
`Surface: the Tauri Rust backend. Files: Client/src-tauri/src/*.rs.\n\n` +
|
||||
`Hunt specifically for: a panic reachable from a Tauri command (unwrap/expect on attacker- or ` +
|
||||
`environment-controlled input) - a panic here can take down the app; a lock held across .await; ` +
|
||||
`state in tauri::State mutated from two commands without coordination; the http_proxy / livekit_proxy / ` +
|
||||
@@ -178,7 +178,7 @@ const SURFACE_LENSES = [
|
||||
{
|
||||
key: 'client-state',
|
||||
prompt:
|
||||
`Surface: TypeScript client state and event handling. Files: Client/tauri-client/src/lib/*.ts and ` +
|
||||
`Surface: TypeScript client state and event handling. Files: Client/src/lib/*.ts and ` +
|
||||
`src/stores/*.ts - prioritize dispatcher.ts, reconcile.ts, read-state.ts, router.ts, roomEventHandlers.ts, ` +
|
||||
`navigation-guard.ts, rate-limiter.ts, channel-navigation.ts, and whatever the churn recon flagged.\n\n` +
|
||||
`Hunt specifically for: a listener/interval/observer registered without a matching teardown (check ` +
|
||||
@@ -505,8 +505,8 @@ const recon = await parallel([
|
||||
`${RULES}\n\nRECON TASK (mechanical, do not hunt bugs yourself):\n` +
|
||||
`Inventory the concurrency and lifecycle surface so the finders know where to look. Report:\n` +
|
||||
` (a) every Server/ non-test .go file containing "go func", "sync.", "chan ", "select {", or "context.WithCancel"\n` +
|
||||
` (b) every Client/tauri-client/src/**/*.ts (non-test) containing "addEventListener", "setInterval", "setTimeout", or "new AbortController"\n` +
|
||||
` (c) every Client/tauri-client/src-tauri/src/*.rs containing "unsafe", "Mutex", "RwLock", "spawn", or "unwrap()"\n` +
|
||||
` (b) every Client/src/**/*.ts (non-test) containing "addEventListener", "setInterval", "setTimeout", or "new AbortController"\n` +
|
||||
` (c) every Client/src-tauri/src/*.rs containing "unsafe", "Mutex", "RwLock", "spawn", or "unwrap()"\n` +
|
||||
`For each file give the path and a rough hit count. Return plain text grouped under (a)/(b)/(c). No commentary, no analysis.`,
|
||||
{ label: 'recon:surface', phase: 'Recon', model: 'haiku', effort: 'xhigh' },
|
||||
),
|
||||
|
||||
@@ -51,13 +51,13 @@ if printf '%s\n' "$staged" | grep -qE '^(docs/protocol-schema\.json|Server/scrip
|
||||
fi
|
||||
|
||||
# ---------- Client (TypeScript) ----------
|
||||
ts_staged=$(printf '%s\n' "$staged" | grep -E '^Client/tauri-client/(src|tests)/.*\.ts$' | grep -v '/generated/')
|
||||
ts_staged=$(printf '%s\n' "$staged" | grep -E '^Client/(src|tests)/.*\.ts$' | grep -v '/generated/')
|
||||
if [ -n "$ts_staged" ]; then
|
||||
if [ ! -d Client/tauri-client/node_modules ]; then
|
||||
printf 'pre-commit: WARNING: node_modules missing in Client/tauri-client; skipping client checks (run npm install there).\n' >&2
|
||||
if [ ! -d Client/node_modules ]; then
|
||||
printf 'pre-commit: WARNING: node_modules missing in Client; skipping client checks (run npm install there).\n' >&2
|
||||
else
|
||||
rel=$(printf '%s\n' "$ts_staged" | sed 's|^Client/tauri-client/||')
|
||||
cd Client/tauri-client || exit 1
|
||||
rel=$(printf '%s\n' "$ts_staged" | sed 's|^Client/||')
|
||||
cd Client || exit 1
|
||||
# shellcheck disable=SC2086
|
||||
npx oxlint $rel || fail "oxlint"
|
||||
# shellcheck disable=SC2086
|
||||
|
||||
+5
-5
@@ -28,7 +28,7 @@ if [ "$changed" = "__all__" ]; then
|
||||
client_changed=1
|
||||
else
|
||||
if printf '%s\n' "$changed" | grep -q '^Server/'; then server_changed=1; fi
|
||||
if printf '%s\n' "$changed" | grep -q '^Client/tauri-client/'; then client_changed=1; fi
|
||||
if printf '%s\n' "$changed" | grep -q '^Client/'; then client_changed=1; fi
|
||||
if printf '%s\n' "$changed" | grep -q '^docs/protocol-schema\.json'; then
|
||||
server_changed=1
|
||||
client_changed=1
|
||||
@@ -49,12 +49,12 @@ if [ "$server_changed" = 1 ] && command -v go >/dev/null 2>&1; then
|
||||
fi
|
||||
|
||||
if [ "$client_changed" = 1 ]; then
|
||||
if [ -d Client/tauri-client/node_modules ]; then
|
||||
if [ -d Client/node_modules ]; then
|
||||
echo "pre-push: client typecheck + eslint..."
|
||||
(cd Client/tauri-client && npm run -s typecheck) || fail "tsc --noEmit"
|
||||
(cd Client/tauri-client && npx eslint src/) || fail "eslint"
|
||||
(cd Client && npm run -s typecheck) || fail "tsc --noEmit"
|
||||
(cd Client && npx eslint src/) || fail "eslint"
|
||||
else
|
||||
printf 'pre-push: WARNING: node_modules missing in Client/tauri-client; skipping client checks.\n' >&2
|
||||
printf 'pre-push: WARNING: node_modules missing in Client; skipping client checks.\n' >&2
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ updates:
|
||||
|
||||
# Tauri client npm dependencies
|
||||
- package-ecosystem: npm
|
||||
directory: /Client/tauri-client
|
||||
directory: /Client
|
||||
schedule:
|
||||
interval: weekly
|
||||
day: monday
|
||||
@@ -58,7 +58,7 @@ updates:
|
||||
|
||||
# Tauri Rust/Cargo dependencies
|
||||
- package-ecosystem: cargo
|
||||
directory: /Client/tauri-client/src-tauri
|
||||
directory: /Client/src-tauri
|
||||
schedule:
|
||||
interval: weekly
|
||||
day: monday
|
||||
|
||||
+24
-24
@@ -119,7 +119,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: Client/tauri-client/
|
||||
working-directory: Client/
|
||||
steps:
|
||||
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
|
||||
|
||||
@@ -127,7 +127,7 @@ jobs:
|
||||
with:
|
||||
node-version: 24
|
||||
cache: npm
|
||||
cache-dependency-path: Client/tauri-client/package-lock.json
|
||||
cache-dependency-path: Client/package-lock.json
|
||||
|
||||
- name: Install npm dependencies
|
||||
run: npm ci
|
||||
@@ -177,7 +177,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: Client/tauri-client/
|
||||
working-directory: Client/
|
||||
steps:
|
||||
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
|
||||
|
||||
@@ -185,7 +185,7 @@ jobs:
|
||||
with:
|
||||
node-version: 24
|
||||
cache: npm
|
||||
cache-dependency-path: Client/tauri-client/package-lock.json
|
||||
cache-dependency-path: Client/package-lock.json
|
||||
|
||||
- name: Install npm dependencies
|
||||
run: npm ci
|
||||
@@ -198,7 +198,7 @@ jobs:
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
with:
|
||||
name: client-coverage
|
||||
path: Client/tauri-client/coverage/
|
||||
path: Client/coverage/
|
||||
retention-days: 7
|
||||
|
||||
# Rust unit tests used to live inside tauri-build, which only runs on PRs to
|
||||
@@ -211,7 +211,7 @@ jobs:
|
||||
timeout-minutes: 30
|
||||
defaults:
|
||||
run:
|
||||
working-directory: Client/tauri-client/src-tauri/
|
||||
working-directory: Client/src-tauri/
|
||||
steps:
|
||||
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
|
||||
|
||||
@@ -236,7 +236,7 @@ jobs:
|
||||
- name: Rust cache
|
||||
uses: swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2
|
||||
with:
|
||||
workspaces: Client/tauri-client/src-tauri
|
||||
workspaces: Client/src-tauri
|
||||
|
||||
- name: Clippy lint (including test targets)
|
||||
run: cargo clippy --all-targets -- -D warnings
|
||||
@@ -264,7 +264,7 @@ jobs:
|
||||
timeout-minutes: 25
|
||||
defaults:
|
||||
run:
|
||||
working-directory: Client/tauri-client/
|
||||
working-directory: Client/
|
||||
steps:
|
||||
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
|
||||
|
||||
@@ -272,7 +272,7 @@ jobs:
|
||||
with:
|
||||
node-version: 24
|
||||
cache: npm
|
||||
cache-dependency-path: Client/tauri-client/package-lock.json
|
||||
cache-dependency-path: Client/package-lock.json
|
||||
|
||||
- name: Install npm dependencies
|
||||
run: npm ci
|
||||
@@ -295,8 +295,8 @@ jobs:
|
||||
with:
|
||||
name: playwright-report
|
||||
path: |
|
||||
Client/tauri-client/playwright-report/
|
||||
Client/tauri-client/test-results/
|
||||
Client/playwright-report/
|
||||
Client/test-results/
|
||||
retention-days: 7
|
||||
|
||||
# Admin-panel journey against a REAL server (no mocks): start-server.sh
|
||||
@@ -318,7 +318,7 @@ jobs:
|
||||
timeout-minutes: 20
|
||||
defaults:
|
||||
run:
|
||||
working-directory: Client/tauri-client/
|
||||
working-directory: Client/
|
||||
steps:
|
||||
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
|
||||
|
||||
@@ -331,7 +331,7 @@ jobs:
|
||||
with:
|
||||
node-version: 24
|
||||
cache: npm
|
||||
cache-dependency-path: Client/tauri-client/package-lock.json
|
||||
cache-dependency-path: Client/package-lock.json
|
||||
|
||||
- name: Install npm dependencies
|
||||
run: npm ci
|
||||
@@ -348,8 +348,8 @@ jobs:
|
||||
with:
|
||||
name: admin-e2e-report
|
||||
path: |
|
||||
Client/tauri-client/playwright-report/
|
||||
Client/tauri-client/test-results/
|
||||
Client/playwright-report/
|
||||
Client/test-results/
|
||||
retention-days: 7
|
||||
|
||||
# Blocking e2e subset: the parity-feature specs (tagged "@parity"), covering
|
||||
@@ -365,7 +365,7 @@ jobs:
|
||||
timeout-minutes: 15
|
||||
defaults:
|
||||
run:
|
||||
working-directory: Client/tauri-client/
|
||||
working-directory: Client/
|
||||
steps:
|
||||
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
|
||||
|
||||
@@ -373,7 +373,7 @@ jobs:
|
||||
with:
|
||||
node-version: 24
|
||||
cache: npm
|
||||
cache-dependency-path: Client/tauri-client/package-lock.json
|
||||
cache-dependency-path: Client/package-lock.json
|
||||
|
||||
- name: Install npm dependencies
|
||||
run: npm ci
|
||||
@@ -390,8 +390,8 @@ jobs:
|
||||
with:
|
||||
name: playwright-report-parity
|
||||
path: |
|
||||
Client/tauri-client/playwright-report/
|
||||
Client/tauri-client/test-results/
|
||||
Client/playwright-report/
|
||||
Client/test-results/
|
||||
retention-days: 7
|
||||
|
||||
# Image build is verification only, so it is skipped on dev to keep day-to-day
|
||||
@@ -457,7 +457,7 @@ jobs:
|
||||
runs-on: ${{ matrix.os }}
|
||||
defaults:
|
||||
run:
|
||||
working-directory: Client/tauri-client/
|
||||
working-directory: Client/
|
||||
steps:
|
||||
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
|
||||
|
||||
@@ -465,7 +465,7 @@ jobs:
|
||||
with:
|
||||
node-version: 24
|
||||
cache: npm
|
||||
cache-dependency-path: Client/tauri-client/package-lock.json
|
||||
cache-dependency-path: Client/package-lock.json
|
||||
|
||||
- name: Install Linux system dependencies
|
||||
if: startsWith(matrix.os, 'ubuntu')
|
||||
@@ -491,20 +491,20 @@ jobs:
|
||||
- name: Rust cache
|
||||
uses: swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2
|
||||
with:
|
||||
workspaces: Client/tauri-client/src-tauri
|
||||
workspaces: Client/src-tauri
|
||||
|
||||
- name: Install npm dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Clippy lint (Rust)
|
||||
working-directory: Client/tauri-client/src-tauri/
|
||||
working-directory: Client/src-tauri/
|
||||
run: cargo clippy -- -D warnings
|
||||
|
||||
# Rust unit tests moved to the standalone `rust-tests` job so they run on
|
||||
# every event, not just PRs to main.
|
||||
|
||||
- name: Security audit (Rust dependencies)
|
||||
working-directory: Client/tauri-client/src-tauri/
|
||||
working-directory: Client/src-tauri/
|
||||
run: |
|
||||
cargo install cargo-audit@0.22.1 --quiet
|
||||
cargo audit
|
||||
|
||||
@@ -30,9 +30,9 @@ jobs:
|
||||
shell: bash
|
||||
run: |
|
||||
TAG_VERSION="${GITHUB_REF_NAME#v}"
|
||||
TAURI_VERSION=$(node -p "require('./Client/tauri-client/src-tauri/tauri.conf.json').version")
|
||||
NPM_VERSION=$(node -p "require('./Client/tauri-client/package.json').version")
|
||||
CARGO_VERSION=$(sed -n 's/^version = "\(.*\)"$/\1/p' Client/tauri-client/src-tauri/Cargo.toml | head -1)
|
||||
TAURI_VERSION=$(node -p "require('./Client/src-tauri/tauri.conf.json').version")
|
||||
NPM_VERSION=$(node -p "require('./Client/package.json').version")
|
||||
CARGO_VERSION=$(sed -n 's/^version = "\(.*\)"$/\1/p' Client/src-tauri/Cargo.toml | head -1)
|
||||
fail=0
|
||||
for pair in "tauri.conf.json:$TAURI_VERSION" "package.json:$NPM_VERSION" "Cargo.toml:$CARGO_VERSION"; do
|
||||
file="${pair%%:*}"; ver="${pair#*:}"
|
||||
@@ -56,7 +56,7 @@ jobs:
|
||||
with:
|
||||
node-version: 24
|
||||
cache: npm
|
||||
cache-dependency-path: Client/tauri-client/package-lock.json
|
||||
cache-dependency-path: Client/package-lock.json
|
||||
|
||||
- name: Install Rust
|
||||
uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable
|
||||
@@ -64,14 +64,14 @@ jobs:
|
||||
- name: Rust cache
|
||||
uses: swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2
|
||||
with:
|
||||
workspaces: Client/tauri-client/src-tauri
|
||||
workspaces: Client/src-tauri
|
||||
|
||||
- name: Install npm dependencies
|
||||
working-directory: Client/tauri-client
|
||||
working-directory: Client
|
||||
run: npm ci
|
||||
|
||||
- name: Build Tauri app
|
||||
working-directory: Client/tauri-client
|
||||
working-directory: Client
|
||||
env:
|
||||
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
|
||||
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
|
||||
@@ -81,7 +81,7 @@ jobs:
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir -p release-staging
|
||||
NSIS_DIR="Client/tauri-client/src-tauri/target/release/bundle/nsis"
|
||||
NSIS_DIR="Client/src-tauri/target/release/bundle/nsis"
|
||||
INSTALLER=$(find "$NSIS_DIR" -name "*.exe" | head -1)
|
||||
cp "$INSTALLER" release-staging/
|
||||
NSIS_ZIP=$(find "$NSIS_DIR" -name "*_x64-setup.nsis.zip" ! -name "*.sig" | head -1)
|
||||
@@ -108,7 +108,7 @@ jobs:
|
||||
with:
|
||||
node-version: 24
|
||||
cache: npm
|
||||
cache-dependency-path: Client/tauri-client/package-lock.json
|
||||
cache-dependency-path: Client/package-lock.json
|
||||
|
||||
- name: Install Linux system dependencies
|
||||
run: |
|
||||
@@ -131,14 +131,14 @@ jobs:
|
||||
- name: Rust cache
|
||||
uses: swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2
|
||||
with:
|
||||
workspaces: Client/tauri-client/src-tauri
|
||||
workspaces: Client/src-tauri
|
||||
|
||||
- name: Install npm dependencies
|
||||
working-directory: Client/tauri-client
|
||||
working-directory: Client
|
||||
run: npm ci
|
||||
|
||||
- name: Build Tauri app (AppImage + deb)
|
||||
working-directory: Client/tauri-client
|
||||
working-directory: Client
|
||||
env:
|
||||
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
|
||||
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
|
||||
@@ -149,7 +149,7 @@ jobs:
|
||||
# EGL_BAD_PARAMETER). Strip them and regenerate the updater artifact +
|
||||
# signatures for the patched image.
|
||||
- name: Strip host-incompatible libs from AppImage and re-sign
|
||||
working-directory: Client/tauri-client
|
||||
working-directory: Client
|
||||
shell: bash
|
||||
env:
|
||||
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
|
||||
@@ -173,7 +173,7 @@ jobs:
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir -p linux-staging
|
||||
BUNDLE_DIR="Client/tauri-client/src-tauri/target/release/bundle"
|
||||
BUNDLE_DIR="Client/src-tauri/target/release/bundle"
|
||||
# AppImage
|
||||
APPIMAGE=$(find "$BUNDLE_DIR/appimage" -name "*.AppImage" ! -name "*.sig" | head -1)
|
||||
if [ -n "$APPIMAGE" ] && [ -f "$APPIMAGE" ]; then cp "$APPIMAGE" linux-staging/; fi
|
||||
@@ -298,7 +298,7 @@ jobs:
|
||||
with:
|
||||
node-version: 24
|
||||
cache: npm
|
||||
cache-dependency-path: Client/tauri-client/package-lock.json
|
||||
cache-dependency-path: Client/package-lock.json
|
||||
|
||||
- name: Install Linux system dependencies
|
||||
run: |
|
||||
@@ -321,14 +321,14 @@ jobs:
|
||||
- name: Rust cache
|
||||
uses: swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2
|
||||
with:
|
||||
workspaces: Client/tauri-client/src-tauri
|
||||
workspaces: Client/src-tauri
|
||||
|
||||
- name: Install npm dependencies
|
||||
working-directory: Client/tauri-client
|
||||
working-directory: Client
|
||||
run: npm ci
|
||||
|
||||
- name: Build Tauri app (AppImage + deb)
|
||||
working-directory: Client/tauri-client
|
||||
working-directory: Client
|
||||
env:
|
||||
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
|
||||
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
|
||||
@@ -336,7 +336,7 @@ jobs:
|
||||
|
||||
# Same strip + re-sign as the x86_64 job — see the comment there.
|
||||
- name: Strip host-incompatible libs from AppImage and re-sign
|
||||
working-directory: Client/tauri-client
|
||||
working-directory: Client
|
||||
shell: bash
|
||||
env:
|
||||
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
|
||||
@@ -360,7 +360,7 @@ jobs:
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir -p linux-arm64-staging
|
||||
BUNDLE_DIR="Client/tauri-client/src-tauri/target/release/bundle"
|
||||
BUNDLE_DIR="Client/src-tauri/target/release/bundle"
|
||||
# AppImage + updater artifact (.tar.gz) + signatures. Every filename
|
||||
# must carry the arch: FindClientAssets matches on the
|
||||
# _aarch64.AppImage.tar.gz suffix, and arch-less names would collide
|
||||
@@ -465,7 +465,7 @@ jobs:
|
||||
with:
|
||||
node-version: 24
|
||||
cache: npm
|
||||
cache-dependency-path: Client/tauri-client/package-lock.json
|
||||
cache-dependency-path: Client/package-lock.json
|
||||
|
||||
- name: Download Windows client assets
|
||||
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
|
||||
@@ -532,7 +532,7 @@ jobs:
|
||||
"$VERSION" "$WIN_HASH" "$WIN_HASH" "$LINUX_HASH" > windows/server-update-manifest.json
|
||||
|
||||
- name: Sign server update assets
|
||||
working-directory: Client/tauri-client
|
||||
working-directory: Client
|
||||
shell: bash
|
||||
env:
|
||||
SERVER_UPDATE_SIGNING_PRIVATE_KEY: ${{ secrets.SERVER_UPDATE_SIGNING_PRIVATE_KEY }}
|
||||
@@ -542,8 +542,8 @@ jobs:
|
||||
printf '%s' "$SERVER_UPDATE_SIGNING_PRIVATE_KEY" > "$KEY_PATH"
|
||||
trap 'rm -f "$KEY_PATH"' EXIT
|
||||
npm ci
|
||||
npx tauri signer sign -f "$KEY_PATH" -p "$SERVER_UPDATE_SIGNING_PRIVATE_KEY_PASSWORD" ../../windows/chatserver.exe
|
||||
npx tauri signer sign -f "$KEY_PATH" -p "$SERVER_UPDATE_SIGNING_PRIVATE_KEY_PASSWORD" ../../windows/server-update-manifest.json
|
||||
npx tauri signer sign -f "$KEY_PATH" -p "$SERVER_UPDATE_SIGNING_PRIVATE_KEY_PASSWORD" ../windows/chatserver.exe
|
||||
npx tauri signer sign -f "$KEY_PATH" -p "$SERVER_UPDATE_SIGNING_PRIVATE_KEY_PASSWORD" ../windows/server-update-manifest.json
|
||||
|
||||
# Fail closed before publishing: prove the freshly signed assets verify
|
||||
# against the pinned public key that ships inside the server binary.
|
||||
|
||||
+4
-4
@@ -36,8 +36,8 @@ docs/security-findings/
|
||||
|
||||
# Mutation-testing output (npm run test:mutate). Local-only by design: a
|
||||
# surviving-mutant report maps exactly which behaviour nothing tests.
|
||||
Client/tauri-client/.stryker-tmp/
|
||||
Client/tauri-client/reports/
|
||||
Client/.stryker-tmp/
|
||||
Client/reports/
|
||||
|
||||
# Server runtime artifacts
|
||||
Server/chatserver.exe
|
||||
@@ -65,7 +65,7 @@ Client/login-mockup.html
|
||||
Client/ui-mockup.html
|
||||
|
||||
# Tauri typegen (auto-generated IPC bindings)
|
||||
Client/tauri-client/src/generated/
|
||||
Client/src/generated/
|
||||
.typecache
|
||||
|
||||
# Node modules
|
||||
@@ -103,7 +103,7 @@ Client/CLIENT-REVIEW.md
|
||||
.serena/
|
||||
|
||||
# Client env (holds API keys - never commit)
|
||||
Client/tauri-client/.env
|
||||
Client/.env
|
||||
|
||||
# Rust review output
|
||||
.rust-review-results/
|
||||
|
||||
Generated
+442
-442
File diff suppressed because it is too large
Load Diff
+418
-418
File diff suppressed because it is too large
Load Diff
@@ -1,9 +1,9 @@
|
||||
# OwnCord
|
||||
|
||||
Self-hosted chat platform (alpha). `Server/` is a Go 1.26 REST + WebSocket
|
||||
server over SQLite with LiveKit voice/video; `Client/tauri-client/` is a Tauri
|
||||
server over SQLite with LiveKit voice/video; `Client/` is a Tauri
|
||||
v2 desktop app (TypeScript frontend, thin Rust backend). Per-component detail
|
||||
lives in `Server/CLAUDE.md` and `Client/tauri-client/CLAUDE.md`; the protocol
|
||||
lives in `Server/CLAUDE.md` and `Client/CLAUDE.md`; the protocol
|
||||
and schema are documented in `docs/protocol.md`, `docs/schema.md`, and
|
||||
`docs/architecture/README.md`.
|
||||
|
||||
@@ -14,8 +14,8 @@ CI fails on drift, and the next generator run silently discards your edit.
|
||||
| Generated | Source of truth | Workflow |
|
||||
| --- | --- | --- |
|
||||
| `Server/db/dbgen/` | `Server/db/queries/*.sql`, `Server/migrations/` | `db-change` skill |
|
||||
| `Server/ws/message_types.go` **and** `Client/tauri-client/src/lib/protocolTypes.ts` | `docs/protocol-schema.json` | `protocol-change` skill |
|
||||
| `Client/tauri-client/src/generated/` | `tauri-typegen` | CI patches known typegen bugs — see `.github/workflows/ci.yml` |
|
||||
| `Server/ws/message_types.go` **and** `Client/src/lib/protocolTypes.ts` | `docs/protocol-schema.json` | `protocol-change` skill |
|
||||
| `Client/src/generated/` | `tauri-typegen` | CI patches known typegen bugs — see `.github/workflows/ci.yml` |
|
||||
|
||||
## Knowledge graph (graphify)
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
SERVER_DIR="$(cd "$SCRIPT_DIR/../../../../../Server" && pwd)"
|
||||
SERVER_DIR="$(cd "$SCRIPT_DIR/../../../../Server" && pwd)"
|
||||
PORT="${OWNCORD_ADMIN_E2E_PORT:-18446}"
|
||||
|
||||
RUN_DIR="$(mktemp -d -t owncord-admin-e2e-XXXXXX)"
|
||||
|
||||
@@ -10,7 +10,7 @@ import { JSDOM } from "jsdom";
|
||||
import { readFileSync } from "node:fs";
|
||||
import path from "node:path";
|
||||
|
||||
const ADMIN_HTML_PATH = path.resolve(__dirname, "../../../../Server/admin/static/index.html");
|
||||
const ADMIN_HTML_PATH = path.resolve(__dirname, "../../../Server/admin/static/index.html");
|
||||
const ADMIN_HTML_SOURCE = readFileSync(ADMIN_HTML_PATH, "utf8");
|
||||
|
||||
// The page's own <script> is a classic (non-module) script, so its top-level
|
||||
|
||||
@@ -145,7 +145,7 @@ cd Server
|
||||
CGO_ENABLED=0 go build -o chatserver -ldflags "-s -w -X main.version=1.2.0-alpha.3" .
|
||||
|
||||
# Client
|
||||
cd Client/tauri-client
|
||||
cd Client
|
||||
npm install
|
||||
npm run tauri build
|
||||
```
|
||||
@@ -158,7 +158,7 @@ cd Server
|
||||
go test ./...
|
||||
|
||||
# Client
|
||||
cd Client/tauri-client
|
||||
cd Client
|
||||
npm run typecheck
|
||||
npm run lint
|
||||
npm test
|
||||
|
||||
+1
-1
@@ -86,7 +86,7 @@ protocol-generate:
|
||||
|
||||
protocol-verify:
|
||||
go run ./scripts/genprotocol
|
||||
@git diff --exit-code ws/message_types.go ../Client/tauri-client/src/lib/protocolTypes.ts || ( \
|
||||
@git diff --exit-code ws/message_types.go ../Client/src/lib/protocolTypes.ts || ( \
|
||||
echo "ERROR: generated protocol constants are stale. Run 'make protocol-generate' and commit the result." ; \
|
||||
exit 1 ; \
|
||||
)
|
||||
|
||||
@@ -40,7 +40,7 @@ type schema struct {
|
||||
func main() {
|
||||
schemaPath := flag.String("schema", "../docs/protocol-schema.json", "path to protocol-schema.json")
|
||||
goOut := flag.String("go-out", "ws/message_types.go", "path to the generated Go file")
|
||||
tsOut := flag.String("ts-out", "../Client/tauri-client/src/lib/protocolTypes.ts", "path to the generated TypeScript file")
|
||||
tsOut := flag.String("ts-out", "../Client/src/lib/protocolTypes.ts", "path to the generated TypeScript file")
|
||||
flag.Parse()
|
||||
|
||||
raw, err := os.ReadFile(*schemaPath)
|
||||
|
||||
@@ -43,7 +43,7 @@ var onEventAttr = regexp.MustCompile(`(?i)<[a-z/][^>]*\bon\w+\s*=`)
|
||||
// Fuzzing confirmed the bare-substring version false-positives on plain
|
||||
// text (seed "jAvAsCript:0"), and the client's own markdown renderer
|
||||
// independently refuses to autolink a javascript: pseudo-URL (see
|
||||
// tauri-client/tests/unit/content-markdown.test.ts, "does not autolink a
|
||||
// Client/tests/unit/content-markdown.test.ts, "does not autolink a
|
||||
// javascript: pseudo-URL"), so plain-text "javascript:" is not exploitable
|
||||
// through any known rendering path.
|
||||
var jsURLInTag = regexp.MustCompile(`(?i)<[a-z/][^>]*\bjavascript:`)
|
||||
|
||||
@@ -628,7 +628,7 @@ func TestAssetFilenameFromURL(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDefaultServerSignaturePublicKey_DiffersFromTauriUpdaterKey(t *testing.T) {
|
||||
tauriConfigPath := filepath.Clean(filepath.Join("..", "..", "Client", "tauri-client", "src-tauri", "tauri.conf.json"))
|
||||
tauriConfigPath := filepath.Clean(filepath.Join("..", "..", "Client", "src-tauri", "tauri.conf.json"))
|
||||
raw, err := os.ReadFile(tauriConfigPath)
|
||||
if err != nil {
|
||||
t.Fatalf("ReadFile(%s): %v", tauriConfigPath, err)
|
||||
|
||||
@@ -286,7 +286,7 @@ func TestAuthenticateConn_InvalidToken_ReceivesAuthError(t *testing.T) {
|
||||
// returning a genuine error rather than sql.ErrNoRows) must NOT be reported
|
||||
// as the terminal auth_error frame. The client treats auth_error as
|
||||
// non-recoverable — it stops reconnecting and clears the user's stored
|
||||
// credentials (see Client/tauri-client/src/lib/ws.ts and dispatcher.ts) — so
|
||||
// credentials (see Client/src/lib/ws.ts and dispatcher.ts) — so
|
||||
// collapsing "DB unreachable" into "bad token" force-logs-out every client
|
||||
// that reconnects during a sub-second SQLite hiccup even though its session
|
||||
// row is perfectly valid. A DB error must surface as a non-terminal error
|
||||
|
||||
@@ -107,4 +107,4 @@ Revisit when that commitment is on the table.
|
||||
|
||||
**Source of truth:** `Server/main.go`, `Server/config/config.go`,
|
||||
`Server/docker-compose.yml`, `docs/deployment.md`, `docs/server-configuration.md`,
|
||||
`Client/tauri-client/src-tauri/src/lib.rs`.
|
||||
`Client/src-tauri/src/lib.rs`.
|
||||
|
||||
@@ -74,6 +74,6 @@ and surface a blocking mismatch modal if it later changes (see
|
||||
[ux/voice-and-e2ee.md](ux/voice-and-e2ee.md)).
|
||||
|
||||
**Source of truth:** `Server/ws/voice_e2ee.go`, `Server/ws/livekit.go`,
|
||||
`Client/tauri-client/src/lib/livekitSession.ts`,
|
||||
`Client/tauri-client/src/lib/e2eeCrypto.ts`,
|
||||
`Client/tauri-client/src-tauri/src/livekit_proxy.rs`.
|
||||
`Client/src/lib/livekitSession.ts`,
|
||||
`Client/src/lib/e2eeCrypto.ts`,
|
||||
`Client/src-tauri/src/livekit_proxy.rs`.
|
||||
|
||||
@@ -10,7 +10,7 @@ pipeline, and a single typed (V2) command dispatch.
|
||||
Message-type constants are **generated**: `docs/protocol-schema.json` is the
|
||||
single source of truth, and `Server/scripts/genprotocol` emits both
|
||||
`Server/ws/message_types.go` and
|
||||
`Client/tauri-client/src/lib/protocolTypes.ts` from it
|
||||
`Client/src/lib/protocolTypes.ts` from it
|
||||
(`make protocol-generate`; CI fails on drift via `make protocol-verify`).
|
||||
The one exception is the plugin command family (`chat_command`,
|
||||
`command_reply`, `plugin_broadcast`), declared by hand in
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
Date: 2026-08-08
|
||||
Status: partially implemented (verified 2026-08-19) — Tier 1a's `make fuzz`
|
||||
target exists (`Server/Makefile`) and Tier 2's five custom ESLint rules
|
||||
shipped 2026-08-08 (`Client/tauri-client/eslint-rules.js`), so the gap table
|
||||
shipped 2026-08-08 (`Client/eslint-rules.js`), so the gap table
|
||||
below is stale for those two rows; Tiers 1b/1c are on-demand npm scripts;
|
||||
Tiers 3–4 remain unimplemented.
|
||||
|
||||
@@ -76,7 +76,7 @@ has no native Windows support (WSL or Docker only), so on this machine it would
|
||||
join `make` as tooling that cannot be run locally. ESLint flat config supports
|
||||
an inline plugin, so custom rules cost no new dependency — and `npx eslint
|
||||
src/` is already a blocking CI gate, which removes the promotion step entirely.
|
||||
Rules live in `Client/tauri-client/eslint-rules.js`, tested with `RuleTester`
|
||||
Rules live in `Client/eslint-rules.js`, tested with `RuleTester`
|
||||
in `tests/unit/eslint-rules.test.ts`. See "Tier 2 — delivered" below.
|
||||
|
||||
## Tier 1 — Turn on what already exists
|
||||
@@ -135,7 +135,7 @@ configured surface that observes that class.
|
||||
|
||||
### 1d. Prerequisite
|
||||
|
||||
Confirm `Client/tauri-client/reports/`, `Client/tauri-client/.stryker-tmp/`,
|
||||
Confirm `Client/reports/`, `Client/.stryker-tmp/`,
|
||||
`Server/coverage-all.out`, and `Server/**/testdata/fuzz/` interim output are
|
||||
covered by `.gitignore` before running any of the above. Add entries where
|
||||
they are missing.
|
||||
|
||||
@@ -81,7 +81,7 @@ no coverage (repo rule: "Target 80%+ coverage; TDD is the expected workflow").
|
||||
|
||||
### W1-2. E2EE key rotation drops peers in 7+ participant calls
|
||||
- **Files:** `Server/ws/voice_e2ee.go` (~line 151);
|
||||
`Client/tauri-client/src/lib/livekitSession.ts` (~lines 1317-1349)
|
||||
`Client/src/lib/livekitSession.ts` (~lines 1317-1349)
|
||||
- **Root cause:** the `voice_e2ee_offer` limit is 5/sec, but the key holder
|
||||
loops over every peer sending one offer each, back-to-back, with no pacing
|
||||
and no retry on `RATE_LIMITED`. With 6+ peers, offers to the 6th+ peer are
|
||||
|
||||
@@ -35,8 +35,8 @@ This is a continuation/handoff doc: what is done, what remains, and how to resum
|
||||
## Resume checklist (do these first)
|
||||
|
||||
1. **Confirm the F4/F8 Rust compiles.** It could not be built in the dev sandbox
|
||||
(no local Tauri builds per `Client/tauri-client/CLAUDE.md`). Run
|
||||
`cd Client/tauri-client/src-tauri && cargo clippy -- -D warnings` (or push and
|
||||
(no local Tauri builds per `Client/CLAUDE.md`). Run
|
||||
`cd Client/src-tauri && cargo clippy -- -D warnings` (or push and
|
||||
let CI do it). Pure `tofu` logic has `#[cfg(test)]` unit tests; the frontend is
|
||||
covered by the 3311-green unit suite.
|
||||
2. ~~**Then F3**~~ — **DONE 2026-07-23** on branch `feat/e2ee-identity-tofu` (see the
|
||||
|
||||
@@ -208,8 +208,8 @@ namespace collisions are confusing for users.
|
||||
| `Server/plugin/manifest.go` | Add `Commands []CommandSpec` to `Manifest`, `validateCommands()`, and a `Manifest.Command(name)` lookup. |
|
||||
| `Server/store/sqlite_plugin_commands.go` | **New file.** CRUD over the `plugin_commands` table. |
|
||||
| `Server/migrations/016_plugin_commands.sql` | New migration. |
|
||||
| `Client/tauri-client/src/state/commands.ts` | **New module.** Caches per-server command list (fetched at `auth_ok` time via a new `commands_list` REST endpoint), feeds the autocomplete UI. |
|
||||
| `Client/tauri-client/src/components/Composer/SlashCommandPopup.tsx` | New component — autocomplete dropdown that opens when the message buffer starts with `/`. |
|
||||
| `Client/src/state/commands.ts` | **New module.** Caches per-server command list (fetched at `auth_ok` time via a new `commands_list` REST endpoint), feeds the autocomplete UI. |
|
||||
| `Client/src/components/Composer/SlashCommandPopup.tsx` | New component — autocomplete dropdown that opens when the message buffer starts with `/`. |
|
||||
| `docs/protocol.md` | Document the four new wire messages. |
|
||||
|
||||
### Permission model
|
||||
@@ -341,7 +341,7 @@ Each step is independently shippable.
|
||||
- [ ] `Server/ws/deps.go` — `CommandDeps`
|
||||
- [ ] `Server/ws/handlers_command_test.go`
|
||||
- [ ] `Server/api/router.go` — `GET /api/v1/commands` (cached schema dump)
|
||||
- [ ] `Client/tauri-client/src/state/commands.ts`
|
||||
- [ ] `Client/tauri-client/src/components/Composer/SlashCommandPopup.tsx`
|
||||
- [ ] `Client/src/state/commands.ts`
|
||||
- [ ] `Client/src/components/Composer/SlashCommandPopup.tsx`
|
||||
- [ ] `docs/protocol.md` — four new wire messages
|
||||
- [ ] `CHANGELOG.md` — Phase D entry
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Tauri HTTP Capability Narrowing — Design
|
||||
|
||||
**Status:** implemented (2026-07-20), re-verified 2026-08-04 — the Decision
|
||||
below landed in `Client/tauri-client/src-tauri/capabilities/default.json`,
|
||||
below landed in `Client/src-tauri/capabilities/default.json`,
|
||||
guarded by `tests/unit/capabilities-scope.test.ts`. The follow-up at the end
|
||||
of this document (move the link-preview fetch behind a Rust command that
|
||||
resolves DNS and rejects private/loopback IPs, closing DNS rebinding and
|
||||
@@ -13,7 +13,7 @@ the remaining outbound host set enumerable.
|
||||
|
||||
## Problem
|
||||
|
||||
`Client/tauri-client/src-tauri/capabilities/default.json` grants three HTTP
|
||||
`Client/src-tauri/capabilities/default.json` grants three HTTP
|
||||
identifiers — `http:allow-fetch`, `http:allow-fetch-send`,
|
||||
`http:allow-fetch-read-body` — each scoped to `https://*`, `https://*:*` and
|
||||
`http://127.0.0.1:*`. In practice that is "the renderer may reach any host on
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"$comment": "Single source of truth for WebSocket protocol message-type constants. Server/ws/message_types.go and Client/tauri-client/src/lib/protocolTypes.ts are generated from this file — edit here, then run `make protocol-generate` in Server/. CI runs `make protocol-verify` to reject drift.",
|
||||
"$comment": "Single source of truth for WebSocket protocol message-type constants. Server/ws/message_types.go and Client/src/lib/protocolTypes.ts are generated from this file — edit here, then run `make protocol-generate` in Server/. CI runs `make protocol-verify` to reject drift.",
|
||||
"version": 1,
|
||||
"client_to_server": [
|
||||
{ "wire": "auth", "go": "MsgTypeAuth", "ts": "AUTH" },
|
||||
|
||||
+1
-1
@@ -62,7 +62,7 @@ cd Server
|
||||
CGO_ENABLED=0 go build -o chatserver -ldflags "-s -w -X main.version=1.2.0-alpha.3" .
|
||||
|
||||
# Client
|
||||
cd Client/tauri-client
|
||||
cd Client
|
||||
npm install
|
||||
npm run tauri build
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user