Commit Graph
40 Commits
Author SHA1 Message Date
asepharyana edbd812c30 feat: fully dynamic custom field badges (auto-style by value, not key name)
CI / typecheck + build (turbo) (push) Canceled after 0s
- CustomFieldBadges now auto-detects styling based on VALUE TYPE+CONTENT
  (number→purple points style, difficulty strings→color-coded, event-like
  strings→purple, categories→orange, status→color-coded)
- DocForm help text made generic (no hardcoded field examples)
- Removed typed CTF fields from DocumentMeta (event/challenge/etc) —
  everything flows through extraFields JSONB for true dynamic behavior
2026-08-21 00:31:36 +07:00
asepharyana b31948faba docs: update PHASES.md with Phase 13 (CTF writeup template system + table rendering fix)
CI / typecheck + build (turbo) (push) Canceled after 0s
2026-08-20 23:58:35 +07:00
asepharyana 040d6cb4ff fix: use explicit path for indexer in deploy to avoid bun run resolving to wrong package.json 2026-08-20 23:54:31 +07:00
asepharyana c611601525 fix: remove db:push from deploy (column manually applied; push is non-interactive-unfriendly)
CI / typecheck + build (turbo) (push) Canceled after 0s
2026-08-20 23:48:42 +07:00
asepharyana 233e88e911 fix: pipe 'yes' to db:push in deploy for non-interactive confirmation 2026-08-20 23:45:05 +07:00
asepharyana 3411dcfa9f fix: make db:push non-fatal in deploy (column may pre-exist)
CI / typecheck + build (turbo) (push) Canceled after 0s
2026-08-20 23:34:51 +07:00
asepharyana 144e124bcb fix: use db:push instead of db:migrate in deploy (schema was initially pushed, not migrated)
CI / typecheck + build (turbo) (push) Canceled after 0s
2026-08-20 23:27:36 +07:00
asepharyana 7fb55590bd feat: dynamic custom frontmatter fields + CTF writeup template system
User requested dynamic (not static) fields for CTF writeup content organization.
Changes:
- DocumentMeta: removed typed CTF fields (event/challenge/category/difficulty/
  points), replaced with single extraFields?: Record<string, string>
- parseFile: any frontmatter key not in the STANDARD set becomes a dynamic
  extra field — fully content-driven, no code changes needed for new fields
- stringifyFile: writes extraFields back to YAML frontmatter for round-trip
  stability
- DocForm: '+ Add field' UI lets creators add ANY metadata key at create/edit
  time
- API routes: splitPayload() auto-separates standard vs custom fields
- Doc page: CustomFieldBadges dynamically renders any custom field with
  auto-styling for common CTF patterns (difficulty→color, points→badge)
- Added db:migrate + db:push scripts; deploy workflow now runs migrations +
  reindexes content on every deploy
- content/writeups/ctf/template/writeup-template.md (template)
- content/writeups/ctf/defcon-quals-2024/pwn-100-ret2win-alignment.md (sample)
- DB column extra_fields (jsonb) already applied to live DB
2026-08-20 23:24:57 +07:00
asepharyana c760c3c087 feat(core): dynamic custom frontmatter fields for CTF writeup metadata
CI / typecheck + build (turbo) (push) Canceled after 0s
- Add extra_fields JSONB column to documents table (migration 0003)
- CreateDocInput/UpdateDocInput: extraFields?: Record<string, string>
- parseFile: extracts non-standard frontmatter keys as extraFields
- stringifyFile: writes extraFields dynamically to YAML frontmatter
- toMeta: spreads extraFields from DB row into DocumentMeta
- DocForm: '+ Add field' UI for content creators to add any metadata
- API routes: splitPayload() separates standard vs custom fields
- Doc page: CustomFieldBadges dynamically renders any custom field
- Add db:migrate / db:push scripts + deploy workflow migration step
- Add CTF writeup template (content/writeups/ctf/template/)
- Add sample DEF CON writeup with event/challenge/category/difficulty/points
- Add @tailwindcss/typography for table rendering (prose classes)
- Add remark-gfm for GitHub Flavored Markdown table parsing
2026-08-20 23:18:57 +07:00
asepharyana 8906ed55a0 fix: add remark-gfm plugin to Markdown component for table rendering
CI / typecheck + build (turbo) (push) Canceled after 0s
react-markdown without remark-gfm doesn't parse GitHub Flavored Markdown
tables — the pipe characters were rendered as plain text instead of <table>
HTML. Fix: install remark-gfm@4 and pass it to ReactMarkdown remarkPlugins.
Also add overflow-x-auto wrapper for table responsiveness.
2026-08-20 22:39:16 +07:00
asepharyana 3cb7879a75 docs: add markdown table to postgres FTS doc for table CSS verification 2026-08-20 22:35:12 +07:00
asepharyana 3938aeb38d fix(web-ui): add @tailwindcss/typography plugin to fix table rendering in docs
The Markdown component uses 'prose' classes (prose-lg prose-headings:)
but @tailwindcss/typography was not installed/registered. Tables and other
MD elements rendered unstyled. Fix: install @tailwindcss/typography@latest,
register via @plugin directive in globals.css, add custom dark-theme
table styles, and remove redundant tailwind.config.js.
2026-08-20 22:32:07 +07:00
asepharyana be9211ef21 feat(web-ui): widen main content container for better card grid layout
CI / typecheck + build (turbo) (push) Canceled after 0s
Increase max-width from 3xl to 4xl/5xl/6xl for xl screens to give the
homepage card grid and docs index more breathing room while keeping
the sidebar at 256px.
2026-08-20 21:46:55 +07:00
asepharyana d9e09dceea feat(web-ui): overhaul homepage with hero section, section overview cards, recent docs strip, and MCP info
- Hero: large headline + tagline + dual CTA buttons + search box
- Section overview: 4-column card grid with icons, descriptions, counts
- Recent documents: card grid sorted by updatedAt
- MCP info footer with server endpoint
- Consistent with docs page layout overhaul
2026-08-20 21:42:52 +07:00
asepharyana d35dd8c887 fix: remove duplicate tag display from section cards
CI / typecheck + build (turbo) (push) Canceled after 0s
2026-08-20 21:38:34 +07:00
asepharyana 44b887a9a0 fix(web-ui): remove client-side onKeyDown from server component to fix 500 on /docs
The search input's onKeyDown handler used window.location.href which is
unavailable during SSR, causing the /docs page to crash. Replaced with
a Link wrapper so it's fully server-rendered.
2026-08-20 21:34:42 +07:00
asepharyana a82af10851 fix: remove prose-lg class (typography plugin not installed) causing 500 on doc pages
CI / typecheck + build (turbo) (push) Canceled after 0s
2026-08-20 21:22:43 +07:00
asepharyana 4bbdbb9647 feat(web-ui): overhaul docs index, doc page, and sidebar with card-based layout
CI / typecheck + build (turbo) (push) Canceled after 0s
- Docs index: hero section with search bar, card grid with metadata/tags, recent strip
- Doc page: section badges, card-style related docs, improved revision history
- Sidebar: section icons, active state highlighting, better typography
2026-08-20 21:18:03 +07:00
asepharyana 977fcc9926 docs: add Phase 12 (MCP client + layout overhaul) to PHASES.md
CI / typecheck + build (turbo) (push) Canceled after 0s
2026-08-20 18:00:42 +07:00
asepharyana ec0abfbd60 feat(mcp-client): MCP client CLI for interacting with MCPedia server
CI / typecheck + build (turbo) (push) Canceled after 0s
New app: apps/mcp-client/ (bun workspace package)

Interactive REPL (bun run chat):
- Connects to MCP server via Streamable HTTP transport
- Tools: /tools, /resources, /search, /ss (semantic), /hybrid,
  /doc, /related, /create (interactive prompts), /update, /delete,
  /index, /queue_status, /help, /quit
- Sends x-webhook-secret header for write tools

One-shot CLI (bun run ask):
- ask <command> [args] — list tools, search, get doc, create, delete, etc.

API client wrapper (src/client.ts):
- McpediaClient class with typed methods for all 13 MCP tools + 5 resources
- StreamableHTTPClientTransport with custom headers (auth)
- Graceful disconnect

Tests (7, all green, no network/DB):
- listTools, getDocument, createDocument, deleteDocument, listResources,
  readResource, header-passing

Deps: @modelcontextprotocol/sdk ^1.29.0, zod ^4.0.0, github-slugger (for web TOC)
2026-08-20 17:57:58 +07:00
asepharyana c400e4a57c docs: update PHASES.md Phase 11 with layout overhaul details
CI / typecheck + build (turbo) (push) Canceled after 0s
2026-08-20 17:10:10 +07:00
asepharyana 050ca518c0 fix(web): Sidebar as client component (no DB during SSG)
- Sidebar.tsx is now "use client" — fetches /api/docs at runtime instead of
  calling listDocuments() during SSG (CI has no DB, causes ECONNREFUSED)
- GET /api/docs added to route.ts (returns doc list for sidebar)
- Removed SidebarContent.tsx (merged into Sidebar.tsx)
- Fixed isAuthorized double-brace typo
2026-08-20 17:06:16 +07:00
asepharyana 167d95c5e8 feat(web): full layout overhaul — Linear design system
CI / typecheck + build (turbo) (push) Canceled after 0s
Complete UI/UX overhaul, not just style changes:

Layout:
- Dark-mode-first (near-black #08090a canvas, whiteOpacity borders)
- Sticky header with brand + nav + theme toggle
- Sticky sidebar (xl+) with hierarchical doc tree
- Main content in max-w-3xl centered column
- Inter font system (via @font-face + CSS vars)
- Font feature settings cv01/ss03 for Linear-geometric Inter

Components rewritten in Linear aesthetic:
- Homepage: editorial-style doc listing with tags, section headers
- Doc page: breadcrumb-style nav links, metadata bar (author/date/tags),
  clean prose, Related + History sections
- TOC: rehype-slug heading anchors + github-slugger matching
- Create/Edit: inline form with Linear-style inputs/buttons
- Login: centered card-style, brand-indigo CTA button
- Docs index: sectioned listing with tag previews
- Search: dark-themed search with result cards + snippets
- ThemeToggle: system-default + localStorage persistence

Typography:
- prose with custom Tailwind classes matching Linear's:
  headings #f7f8f8 font-light, body #d0d6e0,
  links #7170ff with hover #828fff,
  code blocks #191a1b bg with #23252a border

New deps: rehype-slug (heading anchors), github-slugger (TOC matching)
Files: layout.tsx (overhaul), page.tsx, create/, login/, docs/,
       [section]/[...slug]/page.tsx, Sidebar.tsx, ThemeToggle.tsx,
       TOC.tsx, DocForm.tsx, Markdown.tsx, Search page
2026-08-20 16:57:30 +07:00
asepharyana f8b525d10c chore: remove test docs (test-crud-doc, mcp-test) created during live verification
CI / typecheck + build (turbo) (push) Canceled after 0s
2026-08-20 13:45:03 +07:00
asepharyana 8ed8c677e8 fix(web): split PUT/DELETE into /api/docs/[...slug]/route.ts
CI / typecheck + build (turbo) (push) Canceled after 0s
Next.js App Router doesn't match DELETE/PUT on /api/docs/route.ts for
nested paths; need a dynamic segment. POST stays at /api/docs, PUT+DELETE
move to /api/docs/[...slug]. Verified DELETE works locally + via Caddy.
2026-08-20 13:38:26 +07:00
asepharyana 98437cb999 fix(web): /api/docs accepts web cookie OR x-webhook-secret (not both required)
CI / typecheck + build (turbo) (push) Canceled after 0s
Web UI login sets mcpedia_admin cookie; /api/docs/route.ts required the
x-webhook-secret header which the browser form also sends, but the dual-auth
path was brittle. Now accepts either: header (API/MCP style) OR cookie (web
login). Also set ADMIN_PASSWORD on VPS .env and restart web.
2026-08-20 13:30:22 +07:00
asepharyana 1dd16ebcba feat(web): Phase 11 UI/UX — TOC, dark mode toggle, /docs index
- Install rehype-slug (proper heading anchors) + github-slugger (matching TOC)
- TOC component: auto-generated from h2/h3 headings, clickable anchors
- Dark mode toggle: ThemeToggle (localStorage + system default), class-based
- /docs index page (lists all docs by section)
- Markdown.tsx uses rehype-slug for stable heading ids
- globals.css: @custom-variant dark (.dark class) for class-based dark mode
- layout.tsx: nav includes ThemeToggle

Note: per user instruction, installed real deps (rehype-slug, github-slugger,
@types/hast) instead of hacky inline any-cast hacks.
2026-08-20 13:21:53 +07:00
asepharyana b998826b71 chore: remove stale docs/create route (using /create instead)
CI / typecheck + build (turbo) (push) Canceled after 0s
2026-08-20 13:08:35 +07:00
asepharyana 57f90018da feat: Phase 11 — CRUD (create/update/delete) + auth + web UI
- Core: createDocument/updateDocument/deleteDocument (file + DB + revision + chunks)
- Parser: stringifyFile (serialize markdown with frontmatter to disk)
- API: tRPC CRUD routers (auth-gated via requireWriteAuth middleware)
- API: createContext now passes expectedSecret from deps (request-scoped auth)
- MCP: 3 new write tools (create_document, update_document, delete_document)
- Web: /create page + ?edit=1 form, /api/auth/login (cookie-based), /api/docs REST CRUD
- Web: Edit buttons on homepage + doc pages (auth-gated)
- Tests: 8 new tests (5 tRPC CRUD + 3 MCP CRUD auth), 40 total all green
2026-08-20 13:08:27 +07:00
asepharyana 2d974b8952 fix(web): fix doubled section prefix in doc links (404 on click)
CI / typecheck + build (turbo) (push) Canceled after 0s
Home page, search results, and doc page Related links all
generated hrefs as /${section}/${slug} but slug already
includes the section prefix (e.g. 'docs/websocket/contract'),
producing doubled URLs like /docs/docs/websocket/contract → 404.
Fix: href={`/${d.slug}`} everywhere.
2026-08-20 12:33:35 +07:00
asepharyana 9afd383eac docs: add Phase 10 CI/CD deploy findings to PHASES.md
CI / typecheck + build (turbo) (push) Canceled after 0s
2026-08-20 12:26:46 +07:00
asepharyana 1b2e20764c ci(deploy): bump appleboy/ssh-action to @v1 (v1.1.0 had key parsing bug) 2026-08-20 12:16:59 +07:00
asepharyana 339f8432a6 ci(deploy): use appleboy/ssh-action for reliable SSH key handling
echo + manual ssh key writing got 'error in libcrypto' (key mangling)
+ 'too many authentication failures'. Switch to appleboy/ssh-action@v1.1.0
which handles key/permission/identity correctly. Also set
SSH_DEPLOY_HOST=45.127.35.244 (public IP, not Tailscale 100.x).
2026-08-20 12:14:59 +07:00
asepharyana 394f207446 ci(deploy): fix SSH host to public IP (not Tailscale 100.x)
CI / typecheck + build (turbo) (push) Canceled after 0s
2026-08-20 12:08:27 +07:00
asepharyana 9d4545885a ci(deploy): add SSH verbose + accept-new for debugging 2026-08-20 12:00:55 +07:00
asepharyana 543c34820c ci(deploy): fix SSH command quoting (newlines instead of && chaining)
CI / typecheck + build (turbo) (push) Canceled after 0s
2026-08-20 11:59:45 +07:00
asepharyana 5d9e60902f ci: add deploy.yml workflow (SSH deploy triggered on CI success)
CI only builds/tests. Deploy is a separate workflow triggered via
workflow_run after CI passes: pull → bun install → web build → restart
all 4 systemd services (web/api/mcp/worker) over SSH.

Secrets (stored in GitHub):
- SSH_DEPLOY_HOST=100.79.111.61
- SSH_DEPLOY_PORT=22
- SSH_DEPLOY_USER=code

- SSH_DEPLOY_KEY=<ed25519 deploy key added to VPS authorized_keys>
2026-08-20 11:57:11 +07:00
asepharyana 2b2b8d8759 docs: Phase 10 audit — verified all features live, recorded frontmatter fix
CI / typecheck + build (turbo) (push) Canceled after 0s
2026-08-20 11:50:08 +07:00
asepharyana ca2bd19c48 fix(core): strip YAML frontmatter in getDocument before web/MCP render
getDocument preferred the on-disk file via readFileSync (raw), returning
the full frontmatter block as visible text on doc pages and MCP resources.
ReactMarkdown rendered the '---' delimiters as <hr/>, exposing YAML keys
(id/title/type/etc.) as plain paragraphs.

Root cause: getDocument bypassed parseFile's gray-matter stripping.
The indexer correctly stripped frontmatter (DB body was clean), but
getDocument read raw from disk for the 'source of truth' path.

Fix: use parseFile(abs, relPath).body (same as the indexer) so the
on-disk path returns frontmatter-free markdown. DB fallback unchanged.

Affects web doc pages + MCP mcpedia://docs/{+slug} and /chunks resources.
Verified: frontmatter leakage 0/9 doc pages, headings render as <h2>,
browser snapshot clean.
2026-08-20 11:45:37 +07:00
asepharyana 76f778c10d chore(testing): Phase 9 — bun:test suite + CI gating with no-DB fakes
CI / typecheck + build (turbo) (push) Canceled after 0s
Added a real test suite (32 tests, 0 external services) using bun:test with
in-process module mocking for @mcpedia/db, @mcpedia/queue, @mcpedia/core.

Enablers:
- apps/api: extracted createApp(deps?) factory + dashboard.ts module from
  index.ts so the HTTP surface is unit-testable (real queue is lazy-imported).
- packages/core: exported shouldCreateRevision pure predicate; restoreRevision
  gained an opts.reindex seam for the chunk-rebuild contract.
- apps/mcp: renamed smoke.test.ts -> smoke.ts (bun test now owns .test.ts),
  updated stale assertions (10 tools, 4 docs in docs section).
- infra: turbo test task (cache:false), test scripts across packages,
  @types/bun + tsconfig base types, CI 'Test' step after Build.

Packages with tests: embeddings(5), parser(5), search(8), core(4),
mcp(6 auth-gates), api(8 contracts).

All green: typecheck(4/4), test(6/6 pkgs), build(web). Live API verified
/health, /metrics, /dashboard, /hooks/* auth gate on temp port.
2026-08-20 11:12:32 +07:00