mirror of
https://github.com/J3vb/OwnCord.git
synced 2026-09-03 03:50:00 +03:00
59ae4d8ad2a1875f0dd4c26895f56430e071a1a7
4
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
59ae4d8ad2 |
test+feat(phase-bc): pass 4 — test coverage, install endpoint, CHANGELOG
Final in-sandbox completeness pass. Five focused pieces; the remaining items in PHASE_BC_LOCAL_TODO.md after this commit are all genuinely local-only (toolchain, network, native deps). Test coverage (the biggest gap from prior reviews) - Server/plugin/manifest_test.go — pluginNameRegexp accept/reject table, validateRelativePath table, oversized version, unknown permission. - Server/plugin/host_http_test.go — hostAllowed dot-boundary suffix, empty-entry rejection, case insensitivity, FQDN trailing dot. ipAllowed table over loopback, RFC1918, RFC4193 (ULA), RFC6598 (CGN), link-local, multicast, unspecified — both v4 and v6 — plus public-IP accept cases. - Server/plugin/loader_test.go — rejectSymlinksUnder catches direct and nested symlinks; scanPluginDirectory rejects a plugin whose entrypoint is a symlink. Skipped on Windows where symlink creation needs elevation. - Server/plugin/host_ui_test.go — AssetHandler serves declared files, rejects undeclared files (404), rejects path traversal, supports nested asset paths. - Server/ws/hub_seedseq_test.go — SeedSeq monotonic, never-backwards, concurrent CAS safety, integration with nextSeq. - Server/ws/extract_event_type_test.go — table covering happy paths, control char rejection, escaped quote rejection, length cap (64), empty/missing/non-JSON inputs. Plugin install endpoint (closes a real feature gap) - Server/plugin/registry.go — InstallFromZip extracts a plugin .zip into a staging directory under cfg.Directory, validates it zip-slip safe (cleaned-path Rel check), refuses non-regular entries, refuses symlinks, caps compressed at 16 MiB and uncompressed total at 64 MiB (each file gated by io.CopyN against the remaining budget). Manifest is parsed at the staged root, then atomically renamed into the canonical plugin directory and registered via the existing installFromDisk path. - Server/api/plugins_handler.go — POST /install accepts multipart with one "plugin" file part, http.MaxBytesReader caps the request body, io.LimitReader caps the in-memory buffer, calls Registry.InstallFromZip, returns 201 with the new plugin name. The endpoint inherits the Pass 2 admin auth + IP gate (mounted under r.Use(admin.RequireAdminAuth)). Protocol surface - Server/ws/serve.go — buildAuthOK now takes replaySource and includes it in the auth_ok payload as "replay_source": "none" | "buffer" | "db". Two call sites updated: reconnect path passes the existing local, fresh-connect path passes "none". Test export updated to pass "none". CI build-tag matrix - .github/workflows/ci.yml — three new steps inside server-build-test build the server with -tags otel, -tags wazero, and -tags otel,wazero. All three are continue-on-error: true until the upstream OTel and wazero modules land in go.mod (tracked in PHASE_BC_LOCAL_TODO.md). Once they do, dropping continue-on-error converts the steps into hard CI gates against tag-boundary drift. Documentation - CHANGELOG.md — new root-level file with curated entries for Phase B, Phase C, security, and behavioural changes operators must know about (notably event_persistence.enabled = true by default). - PHASE_BC_LOCAL_TODO.md — ticks off the install endpoint, the replay_source field, and the existing event_persistence defaultYAML entry. The remaining items are toolchain-bound. After this pass, the in-sandbox completeness ceiling is reached. Everything still pending requires Go 1.25 toolchain, npm install, real OTel SDK + wazero modules, sqlc, postgres backend impl, or tinygo. https://claude.ai/code/session_01UsBsQW2YiA2usk9pnJjAWk |
||
|
|
7476c177b7 |
chore(phase-bc): pass 3 cleanup — perf, observability, hardening
Eight focused follow-ups from the medium-severity review bucket. All
in-sandbox tractable; no module changes, no new dependencies.
Performance
- Drop the defensive memcpy in EventPersister.Enqueue. The hub already
passes a fresh slice from wrapWithSeq and the copy was happening under
seqMu, serializing broadcast throughput. Documented the no-mutate
contract on the call site.
Observability
- AppMetrics gains WSEventsPersistErrors counter; the persister run loop
bumps both it and the existing WSEventsPersisted counter via cached
metrics handle.
- Hub.persistEvent now extracts the real event type ("chat_message",
"voice_join", ...) from the wrapped JSON envelope via a small
no-allocation byte scan instead of recording the generic
"broadcast"/"channel_broadcast" label.
- Added OTel spans + ServiceCallDurationMs histogram entries on one
public method per remaining service: DMService.CreateDM,
VoiceService.JoinChannel, InviteService.CreateInvite,
ModerationService.BanUser, BlockService.BlockUser,
UserService.UpdateProfile. Mirrors the existing pattern from
MessageService.SendMessage.
Hardening
- plugin/loader now Lstat-walks each plugin directory and rejects any
symlink, plus refuses an entrypoint that is itself a symlink. The
asset handler's prefix check stays as defense in depth.
- ipAllowed (plugin HTTP capability) now rejects RFC6598 carrier-grade
NAT (100.64.0.0/10), closing a gap in net.IP.IsPrivate which only
covers RFC1918 + RFC4193.
- Registry.activateAll syncs Instance.Enabled := true after a successful
activate so callers reading the in-memory flag see the live state.
Documentation
- defaultYAML now documents the new event_persistence, telemetry, and
plugins config blocks with their defaults and one-line descriptions.
- PHASE_BC_LOCAL_TODO.md ticks off five items (defaultYAML docs ×2,
remaining service spans, registry wiring already-fixed in Pass 2).
https://claude.ai/code/session_01UsBsQW2YiA2usk9pnJjAWk
|
||
|
|
46aeccc49b |
fix(phase-bc): address review findings — auth, SSRF, seq alignment
Phase B + C review pass: critical security and correctness fixes. Security - S1: plugin admin endpoints now require admin.RequireAdminAuth in addition to AdminIPRestrict. Previously a LAN attacker on the allowed CIDR could list/enable/disable/uninstall plugins without a session. - S2: rewrite plugin HTTPDo allowlist with proper net/url parsing. Empty entries are ignored, suffix matches require a dot boundary, and a custom Dialer rejects loopback / RFC1918 / link-local addresses to close the DNS-rebinding TOCTOU window. Redirects re-validated. - S3 + #9: manifest Name pinned to ^[a-z0-9][a-z0-9_-]{0,63}$, Entrypoint and UI tab assets validated against absolute / "..", NUL byte, backslash and non-canonical paths. Asset handler hardened with filepath.Rel check for symlink and prefix-without-separator escapes. - S5: pluginBridge postMessage handler ignores the pluginId in the message body and uses an e.source -> contentWindow lookup instead, defeating spoofed messages from same-origin scripts. - S8: HTTPDo body capped at 5 MiB via io.LimitReader, redirects bounded to 5 hops. Correctness - Critical seq alignment: PersistEvent now takes the hub-assigned seq as a required parameter so the events table row seq always matches the wrapped payload seq. Hub seeds its in-memory atomic counter from MAX(events.seq) on startup. Drops in the persister queue no longer mis-align row vs payload seq. - #1: live plugin.Registry constructed in main.go BEFORE NewRouter and threaded through; admin handler is no longer wired with nil. - #3: EventPersister.Stop is now safe to call without a prior Start by tracking a started flag — previously deadlocked waiting on done. Wiring - NewRouter signature gains *plugin.Registry; two test callers updated. - admin.RequireAdminAuth exported as a thin wrapper over the existing package-private adminAuthMiddleware. - sqlc query templates updated for the new PersistEvent + GetMaxEventSeq contracts (sqlite + postgres). https://claude.ai/code/session_01UsBsQW2YiA2usk9pnJjAWk |
||
|
|
a2cb224323 |
feat: scaffold Phase B + C (events, telemetry, plugins, Solid.js)
Phase B Step 6 — Solid.js incremental migration
- vite-plugin-solid + solid-js + @solidjs/testing-library in package.json
- vite.config.ts compiles src/components/solid/** as Solid TSX
- tsconfig.json gains jsx: preserve / jsxImportSource: solid-js
- lib/solidAdapter.ts wraps existing custom Stores as Solid signals
- lib/solidMount.ts adapts Solid render to {mount,destroy} contract
- components/solid/Badge.tsx (proof-of-concept leaf)
- components/solid/ChannelListItem.tsx (store-subscribed leaf)
- components/solid/Badge.test.tsx pipeline smoke test
- components/solid/README.md documents the migration recipe
Phase B Step 7 — Event persistence layer
- SQLite + Postgres migrations for the events table
- sqlc query files for both engines
- EventStore interface + SQLite raw-SQL impl + MemStore impl + pg stubs
- ws.EventPersister: async batched writer (queue / flush / drain / drop)
- ws.StartEventPruner: background retention pruner
- hub persists every replay-buffer push and exposes reconnect-tier counters
- serve.handleReconnect: tiered replay (buffer -> DB -> full re-sync)
- EventPersistenceConfig + main.go wiring
- event_persister_test.go covers batching / drops / drain
Phase B Step 8 — OpenTelemetry skeleton
- Server/telemetry package with public Provider/Tracer/Meter/Counter API
- telemetry_default.go (no-op build) + telemetry_otel.go (build tag otel)
- telemetry/metrics.go declares the AppMetrics bundle
- HTTPMiddleware mounted in Chi router (pass-through in default build)
- PrometheusHandler optionally mounted at /metrics
- Spans on MessageService.SendMessage, PermissionService.HasChannelPerm,
ChannelService.ListVisibleChannels
- Reconnect-tier counter wired into the global meter
- TelemetryConfig defaults
Phase C Step 9 — Wazero plugin runtime skeleton
- Server/plugin package: manifest parser, loader, registry, host APIs
(commands, storage, events, http, ui), errors
- sandbox_default.go (no-op) + sandbox_wazero.go (build tag wazero)
- SQLite + Postgres migrations for plugins + plugin_kv tables
- PluginStore interface + impls + pg stubs
- plugin/examples/hello manifest + README
- plugin_test.go covers manifest, loader, capability gating
- api/plugins_handler.go admin REST surface, mounted under admin group
- PluginsConfig + main.go wiring (disabled by default)
- Client: lib/pluginBridge.ts iframe + postMessage host
- Client: components/solid/PluginContainer.tsx Solid host component
Verification
- Default build (no -tags) is intended to compile cleanly with no new
third-party dependencies. The sandbox lacked Go 1.25.0 so go build
could not run; PHASE_BC_LOCAL_TODO.md enumerates the local follow-up
work (npm install, go mod tidy, sqlc-generate, real otel/wazero
wiring, remaining service spans, full Solid migration).
|