Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 316809bf1c | |||
| 32cb6f1d33 | |||
| 73152f2934 | |||
| 18cae51182 | |||
| a07cab97f3 | |||
| bbf14e3067 | |||
| 2de7e13a8a | |||
| d3f2b009bc | |||
| e03cc01109 |
@@ -0,0 +1,35 @@
|
|||||||
|
## 背景
|
||||||
|
|
||||||
|
なぜ必要か。
|
||||||
|
|
||||||
|
## 対象範囲
|
||||||
|
|
||||||
|
- backend:
|
||||||
|
- frontend:
|
||||||
|
- docs:
|
||||||
|
- migration:
|
||||||
|
|
||||||
|
## やること
|
||||||
|
|
||||||
|
- [ ]
|
||||||
|
|
||||||
|
## 受け入れ条件
|
||||||
|
|
||||||
|
- [ ]
|
||||||
|
|
||||||
|
## 実行すべき確認
|
||||||
|
|
||||||
|
- [ ] `cd backend && bundle exec rspec`
|
||||||
|
- [ ] `cd frontend && npm run build`
|
||||||
|
- [ ] `cd frontend && npm run lint`
|
||||||
|
|
||||||
|
## 禁止事項
|
||||||
|
|
||||||
|
- unrelated refactor はしない
|
||||||
|
- 既存 API response shape を壊さない
|
||||||
|
- 認証・認可・BAN を弱めない
|
||||||
|
|
||||||
|
## Codex への指示
|
||||||
|
|
||||||
|
この issue を読んで実装してください。
|
||||||
|
不明点があれば、実装前に調査結果と選択肢を提示してください。
|
||||||
@@ -0,0 +1,143 @@
|
|||||||
|
# AGENTS.md
|
||||||
|
|
||||||
|
## Project overview
|
||||||
|
|
||||||
|
BTRC Hub / タグ広場 is a split Rails API and React frontend repository.
|
||||||
|
|
||||||
|
- Backend: Rails API under `backend/`.
|
||||||
|
- Frontend: React + TypeScript + Vite under `frontend/`.
|
||||||
|
- Docs: lightweight command notes under `docs/`.
|
||||||
|
- There is no README or Makefile at the repository root as of this inspection.
|
||||||
|
|
||||||
|
## Stack
|
||||||
|
|
||||||
|
- Backend: Ruby `3.2.2` from `backend/.ruby-version`, Rails `~> 8.0.2`.
|
||||||
|
- Backend dependencies include `mysql2`, `sqlite3`, `rspec-rails`, `factory_bot_rails`, `rack-cors`, `jwt`, `discard`, `gollum`, `whenever`, `aws-sdk-s3`, `brakeman`, and `rubocop-rails-omakase`.
|
||||||
|
- Frontend: React `^19.1.0`, TypeScript `~5.8.3`, Vite `^6.3.5`.
|
||||||
|
- Frontend data/UI dependencies include Axios, TanStack Query, Tailwind CSS, Framer Motion, Radix UI components, lucide-react, MDX/Markdown tooling, and Zustand.
|
||||||
|
|
||||||
|
## Main directories
|
||||||
|
|
||||||
|
- `backend/app/controllers`: Rails API controllers.
|
||||||
|
- `backend/app/models`: Active Record models.
|
||||||
|
- `backend/app/representations`: API response representation classes.
|
||||||
|
- `backend/app/services`: domain services such as version recording, wiki commit, YouTube sync, and similarity calculation.
|
||||||
|
- `backend/config/routes.rb`: API routes.
|
||||||
|
- `backend/db/migrate`: migrations.
|
||||||
|
- `backend/db/schema.rb`: current schema snapshot.
|
||||||
|
- `backend/lib/tasks`: custom Rake tasks.
|
||||||
|
- `backend/spec`: RSpec tests.
|
||||||
|
- `backend/test`: Rails minitest files that still exist in the tree.
|
||||||
|
- `frontend/src/App.tsx`: frontend route definitions and initial user setup.
|
||||||
|
- `frontend/src/pages`: page-level React components.
|
||||||
|
- `frontend/src/components`: shared and feature components.
|
||||||
|
- `frontend/src/lib`: API client helpers, query keys, prefetchers, and domain helpers.
|
||||||
|
- `frontend/src/stores`: Zustand stores.
|
||||||
|
- `docs/commands.md`: command notes.
|
||||||
|
|
||||||
|
## Commands
|
||||||
|
|
||||||
|
Only list commands that are backed by files inspected in this repository.
|
||||||
|
|
||||||
|
### Backend
|
||||||
|
|
||||||
|
The following binstubs exist under `backend/bin`:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cd backend
|
||||||
|
bin/setup
|
||||||
|
bin/dev
|
||||||
|
bin/rails
|
||||||
|
bin/rake
|
||||||
|
bin/rubocop
|
||||||
|
bin/brakeman
|
||||||
|
bin/kamal
|
||||||
|
bin/thrust
|
||||||
|
```
|
||||||
|
|
||||||
|
Common Rails/Rake usage through existing binstubs:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cd backend
|
||||||
|
bin/rails db:prepare
|
||||||
|
bin/rails db:migrate
|
||||||
|
bin/rails routes
|
||||||
|
bin/rails server
|
||||||
|
bin/rake
|
||||||
|
bin/rubocop
|
||||||
|
bin/brakeman
|
||||||
|
```
|
||||||
|
|
||||||
|
RSpec is present in `Gemfile` and `.rspec` exists:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cd backend
|
||||||
|
bundle exec rspec
|
||||||
|
```
|
||||||
|
|
||||||
|
### Frontend
|
||||||
|
|
||||||
|
The following npm scripts exist in `frontend/package.json`:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cd frontend
|
||||||
|
npm run dev
|
||||||
|
npm run build
|
||||||
|
npm run lint
|
||||||
|
npm run preview
|
||||||
|
```
|
||||||
|
|
||||||
|
`npm run build` runs `tsc -b && vite build`, then `postbuild` runs `node scripts/generate-sitemap.js`.
|
||||||
|
|
||||||
|
Do not write or report `npm test` as a repository command unless a `test` script is added to `frontend/package.json`.
|
||||||
|
|
||||||
|
## Coding style
|
||||||
|
|
||||||
|
- Prefer precise, minimal changes.
|
||||||
|
- Do not flatter or over-explain.
|
||||||
|
- Explain risks directly.
|
||||||
|
- Prefer single quotes for strings unless interpolation or escaping makes double quotes better.
|
||||||
|
- Ruby: never put a space before method-call parentheses.
|
||||||
|
- Ruby: do not use `%w` or `%i`.
|
||||||
|
- TypeScript and Python: use GNU-style spacing before parentheses where syntactically valid.
|
||||||
|
- Do not add production dependencies without explicit approval.
|
||||||
|
|
||||||
|
## Backend rules
|
||||||
|
|
||||||
|
- Inspect existing routes, controllers, models, services, and specs before editing backend behavior.
|
||||||
|
- For API behavior changes, add or update request specs under `backend/spec/requests`.
|
||||||
|
- Prefer RSpec for new backend tests; existing minitest files under `backend/test` do not make minitest the default for new coverage.
|
||||||
|
- Do not weaken authentication, BAN user checks, or IP BAN checks.
|
||||||
|
- Preserve the `X-Transfer-Code` user identification flow unless the task explicitly changes authentication.
|
||||||
|
- Be careful with version tables, `version_no`, optimistic concurrency, wiki revisions, and restore/diff behavior.
|
||||||
|
- Be careful with tag names, tag normalization, implications, similarities, and discard behavior.
|
||||||
|
- Keep migration files and `backend/db/schema.rb` consistent when changing schema.
|
||||||
|
|
||||||
|
## Frontend rules
|
||||||
|
|
||||||
|
- Use `frontend/src/lib/api.ts` for API calls so headers and camelCase conversion stay consistent.
|
||||||
|
- Add or reuse TanStack Query keys through `frontend/src/lib/queryKeys.ts`; avoid ad hoc query key arrays.
|
||||||
|
- Encode URL path-segment values with `encodeURIComponent`.
|
||||||
|
- React hooks must be called unconditionally.
|
||||||
|
- Keep page-level code under `frontend/src/pages` and shared UI/feature code under `frontend/src/components` unless existing patterns point elsewhere.
|
||||||
|
- Match existing Tailwind, component, and import alias conventions.
|
||||||
|
|
||||||
|
## Codex workflow
|
||||||
|
|
||||||
|
- First inspect existing patterns; do not invent new architecture when a local convention exists.
|
||||||
|
- Keep changes scoped to the requested issue.
|
||||||
|
- Do not scan or summarize dependency/generated/runtime directories such as `node_modules`, `dist`, `tmp`, `log`, and `storage` unless explicitly needed.
|
||||||
|
- Before touching wiki, tag, versioning, BAN, IP BAN, or authentication behavior, inspect the related request specs and service objects.
|
||||||
|
- If frontend code changes, run the existing frontend verification commands that apply: `npm run build` and `npm run lint`.
|
||||||
|
- If backend code changes, run the relevant RSpec command; for broad backend changes, run `bundle exec rspec`.
|
||||||
|
- If a verification command cannot be run or fails, report the exact command and failure.
|
||||||
|
|
||||||
|
## Completion criteria
|
||||||
|
|
||||||
|
A task is complete only when:
|
||||||
|
|
||||||
|
- implementation is complete,
|
||||||
|
- relevant verification commands pass, or failures are clearly explained,
|
||||||
|
- unrelated files are not changed,
|
||||||
|
- migrations and schema are consistent when schema changes are made,
|
||||||
|
- user-facing behavior is documented when needed.
|
||||||
@@ -0,0 +1,147 @@
|
|||||||
|
# backend/AGENTS.md
|
||||||
|
|
||||||
|
## Scope
|
||||||
|
|
||||||
|
These rules apply to work under `backend/`.
|
||||||
|
|
||||||
|
This is a Rails API app using Active Record, RSpec, request specs, service objects, representation classes, and version tables for post/tag/wiki history.
|
||||||
|
|
||||||
|
## Commands
|
||||||
|
|
||||||
|
Use commands backed by files and dependencies in this directory:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
bin/setup
|
||||||
|
bin/dev
|
||||||
|
bin/rails
|
||||||
|
bin/rake
|
||||||
|
bin/rubocop
|
||||||
|
bin/brakeman
|
||||||
|
bundle exec rspec
|
||||||
|
```
|
||||||
|
|
||||||
|
Common checks:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
bundle exec rspec
|
||||||
|
bin/rubocop
|
||||||
|
bin/brakeman
|
||||||
|
```
|
||||||
|
|
||||||
|
Common Rails commands:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
bin/rails db:prepare
|
||||||
|
bin/rails db:migrate
|
||||||
|
bin/rails routes
|
||||||
|
bin/rails server
|
||||||
|
```
|
||||||
|
|
||||||
|
After backend behavior changes, run the relevant RSpec files. For broad backend changes, run:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
bundle exec rspec
|
||||||
|
```
|
||||||
|
|
||||||
|
If a command cannot be run or fails, report the exact command and failure.
|
||||||
|
|
||||||
|
## Rails structure
|
||||||
|
|
||||||
|
- `app/controllers`: API controllers.
|
||||||
|
- `app/models`: Active Record models and concerns.
|
||||||
|
- `app/representations`: JSON response shaping.
|
||||||
|
- `app/services`: domain services such as version recorders, wiki commit, YouTube sync, and similarity calculation.
|
||||||
|
- `config/routes.rb`: public API routes.
|
||||||
|
- `db/migrate`: migrations.
|
||||||
|
- `db/schema.rb`: schema snapshot.
|
||||||
|
- `lib/tasks`: custom Rake tasks.
|
||||||
|
- `spec`: RSpec tests.
|
||||||
|
|
||||||
|
Before changing behavior, inspect the matching route, controller, model, service, representation, and spec.
|
||||||
|
|
||||||
|
## Ruby style
|
||||||
|
|
||||||
|
- Prefer precise, minimal changes.
|
||||||
|
- Use single quotes unless interpolation or escaping makes double quotes better.
|
||||||
|
- Do not put a space before Ruby method-call parentheses.
|
||||||
|
- Do not use `%w` or `%i` in new Ruby code.
|
||||||
|
- Keep comments short and useful; avoid narrating obvious code.
|
||||||
|
- Do not add production dependencies without approval.
|
||||||
|
|
||||||
|
## Authentication and authorization
|
||||||
|
|
||||||
|
- Authentication is handled through the `X-Transfer-Code` header in `ApplicationController#authenticate_user`.
|
||||||
|
- `current_user` is set by looking up `User.inheritance_code`.
|
||||||
|
- Do not bypass or weaken the `X-Transfer-Code` flow unless the task explicitly changes authentication.
|
||||||
|
- Unauthenticated write actions should return `:unauthorized` consistently with existing controllers.
|
||||||
|
- Role checks use `User` enum roles: `guest`, `member`, and `admin`.
|
||||||
|
- Use `current_user.gte_member?` for member-or-admin write permissions where existing controllers do so.
|
||||||
|
- Use `current_user.admin?` only for admin-only paths, such as tag child relationship changes.
|
||||||
|
- Do not replace role checks with looser presence checks.
|
||||||
|
|
||||||
|
## BAN and IP BAN
|
||||||
|
|
||||||
|
- `ApplicationController` runs these before actions in order:
|
||||||
|
- `reject_banned_ip_address!`
|
||||||
|
- `authenticate_user`
|
||||||
|
- `reject_banned_user!`
|
||||||
|
- User and IP bans use `banned_at`, not a boolean `banned` column.
|
||||||
|
- `User#banned?` and `IpAddress#banned?` check `banned_at.present?`.
|
||||||
|
- Do not weaken BAN or IP BAN behavior.
|
||||||
|
- If changing request authentication or controller before actions, add or update request specs covering banned users and banned IP addresses.
|
||||||
|
|
||||||
|
## RSpec
|
||||||
|
|
||||||
|
- Prefer RSpec for new backend tests.
|
||||||
|
- Put API behavior coverage under `spec/requests`.
|
||||||
|
- Put model behavior under `spec/models`.
|
||||||
|
- Put service behavior under `spec/services`.
|
||||||
|
- Put Rake task coverage under `spec/tasks`.
|
||||||
|
- `spec/rails_helper.rb` loads `spec/support/**/*.rb`.
|
||||||
|
- Request specs include `AuthHelper` and `JsonHelper`.
|
||||||
|
- `AuthHelper#sign_in_as(user)` stubs `ApplicationController#current_user`; use it when matching existing request spec style.
|
||||||
|
- Add or update request specs for API behavior changes, especially status codes, permissions, response shape, and version conflict behavior.
|
||||||
|
|
||||||
|
## Migrations
|
||||||
|
|
||||||
|
- Keep migrations and `db/schema.rb` consistent.
|
||||||
|
- Use reversible migrations where practical; otherwise define explicit `up` and `down`.
|
||||||
|
- For data backfills inside migrations, follow the existing pattern of defining migration-local `ActiveRecord::Base` classes with `self.table_name`.
|
||||||
|
- Preserve existing indexes, foreign keys, check constraints, and null constraints.
|
||||||
|
- Be careful with MySQL-specific options already present in migrations, such as `after:`.
|
||||||
|
- Do not edit old migrations just to change current behavior unless explicitly requested; add a new migration.
|
||||||
|
|
||||||
|
## Version tables
|
||||||
|
|
||||||
|
- Versioned records include posts, tags, nico tags, and wiki pages.
|
||||||
|
- Current records have `version_no`; version tables have positive `version_no` with unique indexes scoped to the parent record.
|
||||||
|
- Version event types are `create`, `update`, `discard`, and `restore`.
|
||||||
|
- Version rows are readonly through the `VersionRecord` concern.
|
||||||
|
- Use the existing recorder services instead of manually inserting version rows in application code:
|
||||||
|
- `PostVersionRecorder`
|
||||||
|
- `TagVersionRecorder`
|
||||||
|
- `NicoTagVersionRecorder`
|
||||||
|
- `WikiVersionRecorder`
|
||||||
|
- `TagVersioning`
|
||||||
|
- `VersionRecorder` locks the current record, validates sequence consistency, skips unchanged update snapshots, creates the next version row, and updates the record `version_no`.
|
||||||
|
- Do not update versioned records without considering whether a version snapshot must be created.
|
||||||
|
- For optimistic concurrency paths, preserve `base_version_no`, `force`, and `merge` semantics and cover conflicts in request specs.
|
||||||
|
|
||||||
|
## Domain cautions
|
||||||
|
|
||||||
|
- Posts have tag snapshots, parent post implications, original-created ranges, viewed state, and version conflict behavior.
|
||||||
|
- Tags have canonical names, aliases through `TagName`, categories, parent implications, discard behavior, and version snapshots.
|
||||||
|
- Nico tags have separate relation/version behavior; do not treat them like normal editable tags without checking existing code.
|
||||||
|
- Wiki pages involve page content, revisions/history, version rows, title/tag-name behavior, and diff/restore paths.
|
||||||
|
- Materials, theatres, and comments have user and permission checks; inspect the controller before changing them.
|
||||||
|
|
||||||
|
## API responses
|
||||||
|
|
||||||
|
- Use representation classes under `app/representations` when existing endpoints do.
|
||||||
|
- Keep response keys consistent with existing JSON contracts; frontend code expects camelCase conversion client-side, while Rails params and JSON keys are generally snake_case.
|
||||||
|
- Preserve existing HTTP status conventions: `:unauthorized` for no user, `:forbidden` for insufficient role or banned user, `:not_found` for missing records, and `:unprocessable_entity` for validation failures.
|
||||||
|
|
||||||
|
## Files to avoid in routine work
|
||||||
|
|
||||||
|
- Do not inspect or edit `tmp/`, `log/`, `storage/`, `vendor/`, or dependency directories unless explicitly needed.
|
||||||
|
- Do not modify generated schema or migration output without the corresponding migration when schema changes are made.
|
||||||
@@ -0,0 +1,646 @@
|
|||||||
|
# Codex handoff for BTRC Hub / タグ広場
|
||||||
|
|
||||||
|
This document transfers project-specific context from prior ChatGPT-assisted design and review work to Codex.
|
||||||
|
|
||||||
|
Use this file as project background.
|
||||||
|
Use `AGENTS.md`, `backend/AGENTS.md`, and `frontend/AGENTS.md` for concrete coding rules and verification commands.
|
||||||
|
|
||||||
|
## Project identity
|
||||||
|
|
||||||
|
BTRC Hub / タグ広場 is a collaborative knowledge base for collecting, tagging, explaining, and rediscovering Bocchi the Rock creature-related works.
|
||||||
|
|
||||||
|
It is not a generic SNS.
|
||||||
|
It is not a comment board.
|
||||||
|
It is not a service for rehosting external content.
|
||||||
|
It is primarily a structured link, tag, wiki, material, and viewing-party system.
|
||||||
|
|
||||||
|
Core domains:
|
||||||
|
|
||||||
|
1. Posts
|
||||||
|
2. Tags
|
||||||
|
3. Wiki pages
|
||||||
|
4. Materials
|
||||||
|
5. Theatre / watch-party features
|
||||||
|
|
||||||
|
The project is already publicly accessible and indexed by search engines, but it has not been broadly announced. Treat it as a small public production system, not a private prototype.
|
||||||
|
|
||||||
|
## Current stack
|
||||||
|
|
||||||
|
Backend:
|
||||||
|
|
||||||
|
- Ruby 3.2.2
|
||||||
|
- Rails 8.0.2 API
|
||||||
|
- MySQL 8
|
||||||
|
- Active Storage
|
||||||
|
- Cloudflare R2 / S3-compatible storage is expected for uploaded files
|
||||||
|
- RSpec
|
||||||
|
|
||||||
|
Frontend:
|
||||||
|
|
||||||
|
- React 19.1
|
||||||
|
- Vite 6.3
|
||||||
|
- TypeScript 5.8
|
||||||
|
- Axios
|
||||||
|
- TanStack Query
|
||||||
|
- Tailwind CSS
|
||||||
|
- Framer Motion
|
||||||
|
- shadcn-like local components
|
||||||
|
- react-markdown
|
||||||
|
- react-markdown-editor-lite
|
||||||
|
- remark-wiki-autolink
|
||||||
|
|
||||||
|
Batch / background-like tasks:
|
||||||
|
|
||||||
|
- Rake tasks
|
||||||
|
- Nico sync
|
||||||
|
- YouTube sync
|
||||||
|
- Similarity calculation tasks
|
||||||
|
|
||||||
|
## Repository working principle
|
||||||
|
|
||||||
|
Before editing, inspect the existing implementation.
|
||||||
|
|
||||||
|
Do not invent a new architecture when the current repo already has an established convention.
|
||||||
|
|
||||||
|
Keep changes scoped to the requested issue.
|
||||||
|
|
||||||
|
Prefer small, reviewable changes over broad rewrites.
|
||||||
|
|
||||||
|
Do not perform unrelated cleanup in the same patch.
|
||||||
|
|
||||||
|
When a task has design ambiguity, first produce a short investigation and recommended plan. Do not silently choose a risky design.
|
||||||
|
|
||||||
|
## User coding preferences
|
||||||
|
|
||||||
|
General:
|
||||||
|
|
||||||
|
- Prefer single quotes for strings unless interpolation, escaping, or framework convention makes double quotes better.
|
||||||
|
- Do not add production dependencies without explicit approval.
|
||||||
|
- Do not perform broad formatting churn.
|
||||||
|
- Do not convert unrelated files to a different style.
|
||||||
|
|
||||||
|
Ruby:
|
||||||
|
|
||||||
|
- Do not put a space before method-call parentheses.
|
||||||
|
- Do not use `%w`.
|
||||||
|
- Do not use `%i`.
|
||||||
|
- Keep Rails code idiomatic, but preserve the user's style where the repo already uses it.
|
||||||
|
|
||||||
|
TypeScript / Python:
|
||||||
|
|
||||||
|
- The user prefers GNU-style spacing before parentheses where syntactically valid.
|
||||||
|
- Preserve existing project formatting if a formatter or nearby code dictates otherwise.
|
||||||
|
|
||||||
|
## Current authentication model
|
||||||
|
|
||||||
|
The system does not use normal email/password authentication.
|
||||||
|
|
||||||
|
Users are authenticated by inheritance code.
|
||||||
|
|
||||||
|
Frontend:
|
||||||
|
|
||||||
|
- Stores the code in `localStorage.user_code`.
|
||||||
|
- Sends it as the `X-Transfer-Code` header.
|
||||||
|
|
||||||
|
Backend:
|
||||||
|
|
||||||
|
- Looks up `users.inheritance_code`.
|
||||||
|
- Sets `current_user`.
|
||||||
|
|
||||||
|
Roles:
|
||||||
|
|
||||||
|
- `guest`
|
||||||
|
- `member`
|
||||||
|
- `admin`
|
||||||
|
|
||||||
|
Important helper:
|
||||||
|
|
||||||
|
- `User#gte_member?` returns true for `member` and `admin`.
|
||||||
|
|
||||||
|
Never introduce a conventional login assumption unless the issue explicitly asks for it.
|
||||||
|
|
||||||
|
## BAN / abuse-control model
|
||||||
|
|
||||||
|
The backend currently enforces BAN at API level.
|
||||||
|
|
||||||
|
The relevant before_action order is conceptually:
|
||||||
|
|
||||||
|
1. Reject banned IP address.
|
||||||
|
2. Authenticate user if transfer code exists.
|
||||||
|
3. Reject banned user.
|
||||||
|
|
||||||
|
Entities:
|
||||||
|
|
||||||
|
- `users.banned_at`
|
||||||
|
- `ip_addresses.banned_at`
|
||||||
|
- `user_ips`
|
||||||
|
|
||||||
|
IP addresses are stored as binary values using `IPAddr#hton`.
|
||||||
|
|
||||||
|
Do not weaken BAN behavior.
|
||||||
|
|
||||||
|
Do not move BAN checks behind optional authentication.
|
||||||
|
|
||||||
|
Do not make preview, theatre, verify, user creation, or public-looking endpoints bypass BAN without an explicit design decision.
|
||||||
|
|
||||||
|
## Public-operation assumptions
|
||||||
|
|
||||||
|
Current practical operation:
|
||||||
|
|
||||||
|
- A few editor accounts exist.
|
||||||
|
- Meaningful editing is mostly done by the owner.
|
||||||
|
- Read access is already public.
|
||||||
|
- Search engines have indexed the site.
|
||||||
|
- Future editor applications are expected through Discord.
|
||||||
|
- Prospective editors are likely people known in the Bocchi creature community.
|
||||||
|
|
||||||
|
This means security and moderation issues matter even if traffic is still small.
|
||||||
|
|
||||||
|
## Core domain summary
|
||||||
|
|
||||||
|
### Posts
|
||||||
|
|
||||||
|
Posts are external URL-based link records.
|
||||||
|
|
||||||
|
Important properties:
|
||||||
|
|
||||||
|
- `url` is required and unique.
|
||||||
|
- URLs are normalized.
|
||||||
|
- Only HTTP / HTTPS are allowed.
|
||||||
|
- Posts can have thumbnails through Active Storage.
|
||||||
|
- `uploaded_user_id` may be NULL for synced or bot-created posts.
|
||||||
|
- `original_created_from` and `original_created_before` represent a time range for original content creation.
|
||||||
|
- When both original time bounds exist, `from < before` is required.
|
||||||
|
|
||||||
|
Parent/child posts:
|
||||||
|
|
||||||
|
- Current implementation uses `post_implications`.
|
||||||
|
- It is many-to-many.
|
||||||
|
- Do not assume `posts.parent_id`.
|
||||||
|
- Frontend/API clients must send `parent_post_ids`, even when empty.
|
||||||
|
- `parent_post_ids` is parsed as a space-separated ID string.
|
||||||
|
- Self-parenting is invalid.
|
||||||
|
- Missing parent IDs are invalid.
|
||||||
|
|
||||||
|
Versions:
|
||||||
|
|
||||||
|
- `post_versions` stores snapshots.
|
||||||
|
- `version_no` is a per-post sequence.
|
||||||
|
- Snapshot includes title, URL, thumbnail base, tags, parent post IDs, original time bounds, event type, and actor.
|
||||||
|
- Optimistic locking for posts is planned / important, but do not assume it is fully implemented unless the code proves it.
|
||||||
|
|
||||||
|
### Tags
|
||||||
|
|
||||||
|
Tags are central.
|
||||||
|
|
||||||
|
There is separation between tag names and tag entities:
|
||||||
|
|
||||||
|
- `tag_names`
|
||||||
|
- `tags`
|
||||||
|
|
||||||
|
Categories:
|
||||||
|
|
||||||
|
- `deerjikist`
|
||||||
|
- `meme`
|
||||||
|
- `character`
|
||||||
|
- `general`
|
||||||
|
- `material`
|
||||||
|
- `nico`
|
||||||
|
- `meta`
|
||||||
|
|
||||||
|
Alias model:
|
||||||
|
|
||||||
|
- `tag_names.canonical_id` expresses aliases.
|
||||||
|
- `canonical_id = NULL` means canonical name.
|
||||||
|
- `canonical_id != NULL` means alias.
|
||||||
|
- An alias must not point to another alias.
|
||||||
|
- A tag name that already has a tag or wiki page generally must not be aliasified.
|
||||||
|
|
||||||
|
Tag normalization:
|
||||||
|
|
||||||
|
- User-entered tags are normalized through existing backend logic.
|
||||||
|
- Known aliases are canonicalized.
|
||||||
|
- Parent tags are expanded recursively.
|
||||||
|
- `nico:` is normally rejected for manual entry.
|
||||||
|
- Special tags such as tag-request / bot / unknown-deerjikist / video / niconico / youtube must be protected.
|
||||||
|
|
||||||
|
Do not casually change tag normalization, alias resolution, or parent expansion. These affect search, wiki, sync, and historical data.
|
||||||
|
|
||||||
|
### Nico tags
|
||||||
|
|
||||||
|
Nico tags use the `nico` category and have separate versioning.
|
||||||
|
|
||||||
|
Important relation:
|
||||||
|
|
||||||
|
- `nico_tag_relations` maps external Nico tags to internal tags.
|
||||||
|
- `nico_tag_id` must be a Nico category tag.
|
||||||
|
- `tag_id` must not be Nico category.
|
||||||
|
|
||||||
|
Do not allow ordinary manual tag editing to create or corrupt Nico tags.
|
||||||
|
|
||||||
|
### Deerjikists
|
||||||
|
|
||||||
|
Deerjikists map external platform identities to internal `deerjikist` tags.
|
||||||
|
|
||||||
|
Known platforms include:
|
||||||
|
|
||||||
|
- `nico`
|
||||||
|
- `youtube`
|
||||||
|
|
||||||
|
YouTube handles may be normalized to `UC...` channel IDs.
|
||||||
|
|
||||||
|
Do not treat user-facing handles and canonical channel IDs as interchangeable without checking existing code.
|
||||||
|
|
||||||
|
### Wiki
|
||||||
|
|
||||||
|
Wiki pages are a major knowledge layer.
|
||||||
|
|
||||||
|
Important points:
|
||||||
|
|
||||||
|
- Wiki pages are tied to tag-like titles.
|
||||||
|
- Title handling, aliases, and canonical tag names matter.
|
||||||
|
- There is line-level storage / revision-oriented behavior in the current implementation.
|
||||||
|
- There has been design tension between wiki revisions and wiki versions.
|
||||||
|
- Wiki conflict detection using `base_revision_id` exists on the backend side.
|
||||||
|
- Frontend support for conflict detection must be verified before assuming it is complete.
|
||||||
|
|
||||||
|
Do not redesign Wiki storage casually.
|
||||||
|
|
||||||
|
Do not add a second competing history system.
|
||||||
|
|
||||||
|
Do not break existing wiki URLs.
|
||||||
|
|
||||||
|
### Materials
|
||||||
|
|
||||||
|
Materials connect files or reference URLs to `material` or `character` tags.
|
||||||
|
|
||||||
|
Important properties:
|
||||||
|
|
||||||
|
- A material has a `tag_id`.
|
||||||
|
- The tag must be `material` or `character`.
|
||||||
|
- A material requires either `url` or attached `file`.
|
||||||
|
- Active Storage is involved.
|
||||||
|
- Upload/security policy matters more than plain link posting.
|
||||||
|
|
||||||
|
Important unresolved/risky area:
|
||||||
|
|
||||||
|
- Material creation permissions have historically been risky because upload endpoints can be abused.
|
||||||
|
- Prefer `member` or higher for material creation unless the issue explicitly says otherwise.
|
||||||
|
|
||||||
|
### Theatre
|
||||||
|
|
||||||
|
Theatre is an experimental watch-party style feature.
|
||||||
|
|
||||||
|
Known pieces include:
|
||||||
|
|
||||||
|
- Display
|
||||||
|
- Presence
|
||||||
|
- Next post
|
||||||
|
- Comments
|
||||||
|
- Host-like control
|
||||||
|
|
||||||
|
Do not assume theatre has complete CRUD/admin support unless the code proves it.
|
||||||
|
|
||||||
|
Theatre may become expensive if next-item selection uses random DB ordering.
|
||||||
|
|
||||||
|
## Current high-risk areas
|
||||||
|
|
||||||
|
Treat these areas with extra care.
|
||||||
|
|
||||||
|
### Security
|
||||||
|
|
||||||
|
- Preview API SSRF protection.
|
||||||
|
- External iframe / embed CSP.
|
||||||
|
- Markdown link safety.
|
||||||
|
- BAN / IP BAN bypass.
|
||||||
|
- Transfer-code leakage.
|
||||||
|
- Guest write access.
|
||||||
|
- Upload endpoints.
|
||||||
|
- Admin-only tag operations.
|
||||||
|
- System tag mutation.
|
||||||
|
|
||||||
|
### Data integrity
|
||||||
|
|
||||||
|
- Tag alias canonicalization.
|
||||||
|
- Tag parent expansion.
|
||||||
|
- Post parent many-to-many relationships.
|
||||||
|
- Version tables.
|
||||||
|
- `version_no` synchronization.
|
||||||
|
- Schema drift from branch migration contamination.
|
||||||
|
- Wiki revision/version split.
|
||||||
|
- Material version recording.
|
||||||
|
|
||||||
|
### Frontend correctness
|
||||||
|
|
||||||
|
- React Hooks must not be called conditionally.
|
||||||
|
- Role guards are currently spread across components/pages.
|
||||||
|
- TanStack Query keys must not collide between ID/name or ID/title variants.
|
||||||
|
- URL path segments containing tag names or wiki titles must use `encodeURIComponent`.
|
||||||
|
- API response types may allow `null` users for bot or migration data.
|
||||||
|
- Tag autocomplete has had duplicated logic and stale state hazards.
|
||||||
|
|
||||||
|
### Performance
|
||||||
|
|
||||||
|
- Avoid unbounded `limit`.
|
||||||
|
- Avoid `order('RAND()')` for growing tables.
|
||||||
|
- Avoid loading full relations just to count.
|
||||||
|
- Avoid Ruby-side sorting/paging for large histories.
|
||||||
|
- Tag sidebar client-side aggregation can become expensive.
|
||||||
|
- Wiki full-text search needs deliberate indexing/design.
|
||||||
|
|
||||||
|
## Current priority order
|
||||||
|
|
||||||
|
Use this as the default priority unless an issue says otherwise.
|
||||||
|
|
||||||
|
### P0: Safety before broad announcement
|
||||||
|
|
||||||
|
1. Preview API SSRF hardening.
|
||||||
|
2. Material creation permission tightening.
|
||||||
|
3. System tag mutation holes.
|
||||||
|
4. `GET /users/me` transfer-code leakage through query params.
|
||||||
|
5. Limit caps for index/history/comment APIs.
|
||||||
|
6. CSP / iframe sandbox policy.
|
||||||
|
7. Confirm BAN enforcement remains global.
|
||||||
|
|
||||||
|
### P1: Core correctness
|
||||||
|
|
||||||
|
1. Post optimistic locking with `version_no`.
|
||||||
|
2. Wiki edit conflict handling.
|
||||||
|
3. Wiki history/revision model clarification.
|
||||||
|
4. Wiki search truthfulness: implement body search or remove false UI.
|
||||||
|
5. Tag alias/canonical/wiki interaction.
|
||||||
|
6. Tag URL encoding.
|
||||||
|
7. TanStack Query key separation.
|
||||||
|
8. Frontend null-user handling.
|
||||||
|
9. React Hooks rule fixes.
|
||||||
|
10. Material version policy.
|
||||||
|
|
||||||
|
### P2: Operational/admin usability
|
||||||
|
|
||||||
|
1. Admin screens for users, IPs, bans, aliases, and settings.
|
||||||
|
2. Settings table and user settings usage.
|
||||||
|
3. Better tag sidebar.
|
||||||
|
4. Better role guard helpers.
|
||||||
|
5. Better frontend tests.
|
||||||
|
6. Better issue triage and closure of already-implemented issues.
|
||||||
|
|
||||||
|
### P3: Future features
|
||||||
|
|
||||||
|
1. Theatre list/create/edit/admin flow.
|
||||||
|
2. Muted/hidden tags.
|
||||||
|
3. Tag category custom colors.
|
||||||
|
4. Responsive refinements.
|
||||||
|
5. Watch-party improvements.
|
||||||
|
6. Broader embed support.
|
||||||
|
|
||||||
|
## Known issue triage notes
|
||||||
|
|
||||||
|
Some existing issues may already be partially or mostly implemented.
|
||||||
|
|
||||||
|
Before implementing an issue, check code first.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
- Tag search and OR/NOT search may already be mostly implemented.
|
||||||
|
- BAN enforcement may have been implemented after earlier issue drafts.
|
||||||
|
- YouTube sync exists and should not be treated as purely planned.
|
||||||
|
- Parent posts are many-to-many in current schema, even if older issues mention one-to-many.
|
||||||
|
- Some issues may reflect old schema or old branch state.
|
||||||
|
|
||||||
|
When in doubt:
|
||||||
|
|
||||||
|
1. Inspect current code.
|
||||||
|
2. Inspect schema.
|
||||||
|
3. Inspect routes.
|
||||||
|
4. Inspect frontend usage.
|
||||||
|
5. Report whether the issue is implemented, partially implemented, not implemented, or obsolete.
|
||||||
|
6. Only then edit.
|
||||||
|
|
||||||
|
## Verification expectations
|
||||||
|
|
||||||
|
Backend changes:
|
||||||
|
|
||||||
|
- Run RSpec when possible.
|
||||||
|
- Add request specs for API behavior changes.
|
||||||
|
- Add model specs for validation / normalization changes.
|
||||||
|
- Check migrations and schema consistency.
|
||||||
|
- Do not silently ignore pending migrations.
|
||||||
|
|
||||||
|
Frontend changes:
|
||||||
|
|
||||||
|
- Run build.
|
||||||
|
- Run lint if configured.
|
||||||
|
- Run tests if configured.
|
||||||
|
- Add tests for important behavior when the test framework exists.
|
||||||
|
- If frontend tests are not yet installed, state that clearly.
|
||||||
|
|
||||||
|
Full-stack changes:
|
||||||
|
|
||||||
|
- Verify both backend and frontend compile/test paths where possible.
|
||||||
|
- Confirm API response shapes match TypeScript types.
|
||||||
|
- Confirm authorization behavior on both server and UI.
|
||||||
|
|
||||||
|
If commands cannot be run because dependencies are missing, report that explicitly. Do not pretend verification passed.
|
||||||
|
|
||||||
|
## Branch / migration caution
|
||||||
|
|
||||||
|
The project has previously suffered from schema contamination caused by running migrations from another branch.
|
||||||
|
|
||||||
|
Be careful when touching:
|
||||||
|
|
||||||
|
- `db/schema.rb`
|
||||||
|
- migration files
|
||||||
|
- parent post schema
|
||||||
|
- banned / banned_at schema
|
||||||
|
- version_no migrations
|
||||||
|
- wiki asset schema
|
||||||
|
|
||||||
|
Before changing migrations:
|
||||||
|
|
||||||
|
1. Inspect current schema.
|
||||||
|
2. Inspect existing migrations.
|
||||||
|
3. Confirm whether the intended branch already includes related migrations.
|
||||||
|
4. Prefer additive migrations for shared branches.
|
||||||
|
5. Do not edit already-applied production migrations unless explicitly instructed.
|
||||||
|
|
||||||
|
## API design principles
|
||||||
|
|
||||||
|
Prefer explicit server-side authorization.
|
||||||
|
|
||||||
|
Do not rely only on frontend hiding.
|
||||||
|
|
||||||
|
Do not return sensitive codes unnecessarily.
|
||||||
|
|
||||||
|
Use 403 for authorization failures.
|
||||||
|
|
||||||
|
Use 422 for validation failures.
|
||||||
|
|
||||||
|
Use 409 for edit conflicts.
|
||||||
|
|
||||||
|
Do not expose internal exception messages to users.
|
||||||
|
|
||||||
|
Clamp or reject abusive limits consistently.
|
||||||
|
|
||||||
|
Keep response shape stable unless the issue explicitly includes a breaking API change.
|
||||||
|
|
||||||
|
## Frontend design principles
|
||||||
|
|
||||||
|
Use existing route and query-key conventions.
|
||||||
|
|
||||||
|
Use TanStack Query `enabled` rather than conditional hook calls.
|
||||||
|
|
||||||
|
Do not let role-based early returns change hook order.
|
||||||
|
|
||||||
|
Centralize repeated tag autocomplete logic when touching it.
|
||||||
|
|
||||||
|
Use `encodeURIComponent` for tag names and wiki titles in URL path segments.
|
||||||
|
|
||||||
|
Prefer graceful fallback for nullable actors:
|
||||||
|
|
||||||
|
- bot operation
|
||||||
|
- deleted user
|
||||||
|
- migration-created data
|
||||||
|
- external sync
|
||||||
|
|
||||||
|
Do not assume all API user fields are non-null.
|
||||||
|
|
||||||
|
## Testing priorities to add over time
|
||||||
|
|
||||||
|
Frontend tests are especially important because the backend already has more mature RSpec coverage.
|
||||||
|
|
||||||
|
Suggested first frontend tests:
|
||||||
|
|
||||||
|
1. Tag autocomplete.
|
||||||
|
2. Post form tag editing.
|
||||||
|
3. Tag URL encoding.
|
||||||
|
4. Wiki edit conflict UI.
|
||||||
|
5. Role guard behavior.
|
||||||
|
6. Null-user history rendering.
|
||||||
|
7. Dialog behavior.
|
||||||
|
8. Top navigation responsive behavior.
|
||||||
|
|
||||||
|
Backend test priorities:
|
||||||
|
|
||||||
|
1. BAN enforcement across public-looking endpoints.
|
||||||
|
2. Material permissions.
|
||||||
|
3. Preview SSRF rejection.
|
||||||
|
4. System tag protection.
|
||||||
|
5. Post optimistic locking.
|
||||||
|
6. Wiki conflict detection.
|
||||||
|
7. Tag alias/canonical behavior.
|
||||||
|
8. Limit caps.
|
||||||
|
9. Parent post parsing.
|
||||||
|
10. Version recorder behavior.
|
||||||
|
|
||||||
|
## What Codex should not do without explicit approval
|
||||||
|
|
||||||
|
Do not:
|
||||||
|
|
||||||
|
- Replace Rails.
|
||||||
|
- Replace React.
|
||||||
|
- Replace TanStack Query.
|
||||||
|
- Redesign the database.
|
||||||
|
- Rewrite Wiki storage.
|
||||||
|
- Remove version tables.
|
||||||
|
- Change authentication model.
|
||||||
|
- Change role names.
|
||||||
|
- Change tag category names.
|
||||||
|
- Add background job infrastructure.
|
||||||
|
- Add a new UI framework.
|
||||||
|
- Add a new test framework if one already exists.
|
||||||
|
- Add major dependencies.
|
||||||
|
- Change public URL design.
|
||||||
|
- Change production storage configuration.
|
||||||
|
- Remove historical data behavior.
|
||||||
|
- Simplify BAN/security checks.
|
||||||
|
- Treat the site as private-only.
|
||||||
|
|
||||||
|
## Good first Codex tasks
|
||||||
|
|
||||||
|
Start with investigation-only tasks.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```txt
|
||||||
|
Inspect the repository and summarize the Rails, React, TypeScript, and test setup.
|
||||||
|
Do not modify files.
|
||||||
|
List commands that actually exist in this repository.
|
||||||
|
List risks Codex should know before editing.
|
||||||
|
```
|
||||||
|
|
||||||
|
Then small safe patches:
|
||||||
|
|
||||||
|
```txt
|
||||||
|
Fix a React Hooks rule violation in one file.
|
||||||
|
Keep behavior unchanged.
|
||||||
|
Run the relevant frontend verification commands.
|
||||||
|
```
|
||||||
|
|
||||||
|
```txt
|
||||||
|
Add encodeURIComponent around one tag-name URL path segment.
|
||||||
|
Add or update a test if the project has a frontend test setup.
|
||||||
|
Run build/lint.
|
||||||
|
```
|
||||||
|
|
||||||
|
```txt
|
||||||
|
Add a request spec for a known authorization rule.
|
||||||
|
Do not change implementation unless the spec fails for the expected reason.
|
||||||
|
```
|
||||||
|
|
||||||
|
Avoid starting with:
|
||||||
|
|
||||||
|
- Wiki history redesign.
|
||||||
|
- Post versioning redesign.
|
||||||
|
- Full admin screen suite.
|
||||||
|
- Broad frontend refactor.
|
||||||
|
- Database cleanup.
|
||||||
|
- Authentication rewrite.
|
||||||
|
|
||||||
|
## Relationship with ChatGPT
|
||||||
|
|
||||||
|
ChatGPT has been used for:
|
||||||
|
|
||||||
|
- Design review.
|
||||||
|
- Risk analysis.
|
||||||
|
- Prioritization.
|
||||||
|
- Specification reconstruction.
|
||||||
|
- Migration/locking discussions.
|
||||||
|
- Codex migration planning.
|
||||||
|
|
||||||
|
Codex should be used mainly for:
|
||||||
|
|
||||||
|
- Repository inspection.
|
||||||
|
- Localized implementation.
|
||||||
|
- Test addition.
|
||||||
|
- Running verification commands.
|
||||||
|
- Producing small reviewable diffs.
|
||||||
|
|
||||||
|
For ambiguous architecture, Codex should stop and present options rather than implement a guessed design.
|
||||||
|
|
||||||
|
## Current strategic stance
|
||||||
|
|
||||||
|
The project should not be rewritten from scratch.
|
||||||
|
|
||||||
|
The current Rails + React system is acceptable.
|
||||||
|
|
||||||
|
The immediate goal is not elegance.
|
||||||
|
The immediate goal is safe public operation, data integrity, and maintainable incremental improvement.
|
||||||
|
|
||||||
|
Priority is:
|
||||||
|
|
||||||
|
1. Prevent abuse/security incidents.
|
||||||
|
2. Preserve data correctness.
|
||||||
|
3. Make editing safe for multiple users.
|
||||||
|
4. Add tests around fragile frontend behavior.
|
||||||
|
5. Improve admin/operation workflows.
|
||||||
|
6. Optimize performance after obvious dangerous patterns are removed.
|
||||||
|
|
||||||
|
## Final rule
|
||||||
|
|
||||||
|
When current code, old specs, issue drafts, and memory disagree, current code wins.
|
||||||
|
|
||||||
|
When current code is unsafe, write that explicitly and propose a small safe fix.
|
||||||
|
|
||||||
|
When the task is too broad, split it.
|
||||||
|
|
||||||
|
When verification cannot be performed, say exactly what was not verified.
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
# Commands
|
||||||
|
|
||||||
|
## Backend
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cd backend
|
||||||
|
bundle install
|
||||||
|
bundle exec rails db:migrate
|
||||||
|
bundle exec rspec
|
||||||
|
bundle exec rails routes
|
||||||
|
```
|
||||||
|
|
||||||
|
## Frontend
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cd frontend
|
||||||
|
npm install
|
||||||
|
npm run dev
|
||||||
|
npm run build
|
||||||
|
npm run lint
|
||||||
|
npm test
|
||||||
|
```
|
||||||
|
|
||||||
|
### Full verification
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cd backend && bundle exec rspec
|
||||||
|
cd ../frontend && npm run build && npm run lint
|
||||||
|
```
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
# Issue workflow
|
||||||
|
|
||||||
|
## Source of truth
|
||||||
|
|
||||||
|
Gitea Issues are the source of truth for tasks, discussions, labels, milestones, and status.
|
||||||
|
|
||||||
|
Do not copy the full backlog into git.
|
||||||
|
|
||||||
|
Repository documents may define:
|
||||||
|
|
||||||
|
- issue templates
|
||||||
|
- triage rules
|
||||||
|
- Codex task format
|
||||||
|
- verification rules
|
||||||
|
- release checklist
|
||||||
|
|
||||||
|
## Labels
|
||||||
|
|
||||||
|
Recommended labels:
|
||||||
|
|
||||||
|
- `P0`
|
||||||
|
- `P1`
|
||||||
|
- `P2`
|
||||||
|
- `P3`
|
||||||
|
- `security`
|
||||||
|
- `data-integrity`
|
||||||
|
- `backend`
|
||||||
|
- `frontend`
|
||||||
|
- `wiki`
|
||||||
|
- `tags`
|
||||||
|
- `materials`
|
||||||
|
- `theatre`
|
||||||
|
- `codex-ready`
|
||||||
|
- `needs-design`
|
||||||
|
- `blocked`
|
||||||
|
- `good-first-codex-task`
|
||||||
|
|
||||||
|
## Codex-ready criteria
|
||||||
|
|
||||||
|
An issue can be labeled `codex-ready` only when it has:
|
||||||
|
|
||||||
|
- clear background
|
||||||
|
- target area
|
||||||
|
- concrete tasks
|
||||||
|
- acceptance criteria
|
||||||
|
- verification commands
|
||||||
|
- explicit non-goals
|
||||||
|
- no unresolved architecture decision
|
||||||
|
|
||||||
|
## Workflow
|
||||||
|
|
||||||
|
1. Create or refine the issue in Gitea.
|
||||||
|
2. Add labels and milestone.
|
||||||
|
3. If design is unclear, label `needs-design`.
|
||||||
|
4. Discuss design before implementation.
|
||||||
|
5. When scoped enough, label `codex-ready`.
|
||||||
|
6. Give Codex the issue URL or copied issue body.
|
||||||
|
7. Codex creates a branch.
|
||||||
|
8. Codex implements a small patch.
|
||||||
|
9. Codex runs verification commands.
|
||||||
|
10. Human reviews the diff.
|
||||||
|
11. Merge.
|
||||||
|
12. Close the issue from the PR/commit message.
|
||||||
|
|
||||||
|
## Commit message
|
||||||
|
|
||||||
|
Use issue references when possible:
|
||||||
|
|
||||||
|
```txt
|
||||||
|
fix: prevent preview SSRF
|
||||||
|
|
||||||
|
Refs: #123
|
||||||
|
```
|
||||||
|
or
|
||||||
|
```
|
||||||
|
fix: prevent preview SSRF
|
||||||
|
|
||||||
|
Closes: #123
|
||||||
|
```
|
||||||
|
depending on whether the change fully resolves the issue.
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
# Release checklist
|
||||||
|
|
||||||
|
- [ ] Backend specs pass
|
||||||
|
- [ ] Frontend build passes
|
||||||
|
- [ ] No pending migrations
|
||||||
|
- [ ] Preview API SSRF checked
|
||||||
|
- [ ] BAN behavior checked
|
||||||
|
- [ ] CSP checked
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
# Roadmap
|
||||||
|
|
||||||
|
## Public announcement readiness
|
||||||
|
|
||||||
|
- Harden preview API
|
||||||
|
- Tighten material creation permission
|
||||||
|
- Add admin MVP
|
||||||
|
- Improve frontend tests
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
# frontend/AGENTS.md
|
||||||
|
|
||||||
|
## Scope
|
||||||
|
|
||||||
|
These rules apply to work under `frontend/`.
|
||||||
|
|
||||||
|
This is a Vite + React + TypeScript app using TanStack Query, Tailwind CSS, Framer Motion, Radix UI-style components, MDX, and Zustand.
|
||||||
|
|
||||||
|
## Commands
|
||||||
|
|
||||||
|
Use only scripts that exist in `package.json`:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm run dev
|
||||||
|
npm run build
|
||||||
|
npm run lint
|
||||||
|
npm run preview
|
||||||
|
```
|
||||||
|
|
||||||
|
`npm run build` runs `tsc -b && vite build`, and `postbuild` runs `node scripts/generate-sitemap.js`.
|
||||||
|
|
||||||
|
There is currently no `test` script in `package.json`. Do not run or report `npm test` unless a test script is added.
|
||||||
|
|
||||||
|
After frontend changes, run:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm run build
|
||||||
|
npm run lint
|
||||||
|
```
|
||||||
|
|
||||||
|
If either command cannot be run or fails, report the exact command and failure.
|
||||||
|
|
||||||
|
## TypeScript
|
||||||
|
|
||||||
|
- TypeScript is strict. `tsconfig.app.json` enables `strict`, `noUnusedLocals`, `noUnusedParameters`, `erasableSyntaxOnly`, `noFallthroughCasesInSwitch`, and `noUncheckedSideEffectImports`.
|
||||||
|
- Keep types explicit at module boundaries, API helpers, and exported utilities.
|
||||||
|
- Use `import type` for type-only imports.
|
||||||
|
- Prefer existing shared types from `src/types.ts` before adding local duplicate types.
|
||||||
|
- Preserve the repository's existing spacing style in TypeScript, including GNU-style spacing before call parentheses where it is already used.
|
||||||
|
- Prefer single quotes for strings unless interpolation or escaping makes double quotes better.
|
||||||
|
|
||||||
|
## React
|
||||||
|
|
||||||
|
- Use function components.
|
||||||
|
- Existing page components commonly export an anonymous function satisfying `FC`; match nearby file style when editing.
|
||||||
|
- React hooks must be called unconditionally and at the top level of components or custom hooks.
|
||||||
|
- Keep page-level components under `src/pages`.
|
||||||
|
- Keep shared and feature components under `src/components`.
|
||||||
|
- Use `react-router-dom` route params and navigation patterns already present in `src/App.tsx`.
|
||||||
|
- Encode URL path-segment values with `encodeURIComponent`.
|
||||||
|
|
||||||
|
## TanStack Query
|
||||||
|
|
||||||
|
- Use `@tanstack/react-query` for server state.
|
||||||
|
- Query keys should come from `src/lib/queryKeys.ts`; add key builders there instead of using ad hoc arrays in components.
|
||||||
|
- Fetch functions should live in domain helpers under `src/lib`, such as `posts.ts`, `tags.ts`, or `wiki.ts`.
|
||||||
|
- Use `useQueryClient().invalidateQueries` with the shared root keys when mutations affect cached lists or detail views.
|
||||||
|
- The app-wide `QueryClient` is configured in `src/main.tsx`; do not create additional clients in feature code.
|
||||||
|
|
||||||
|
## API calls
|
||||||
|
|
||||||
|
- Use `src/lib/api.ts` for HTTP calls.
|
||||||
|
- The API wrapper attaches `X-Transfer-Code` from `localStorage` and converts non-blob responses to camelCase.
|
||||||
|
- Send Rails snake_case params and request body keys where the backend expects them.
|
||||||
|
- Do not bypass the API wrapper unless there is a specific reason, such as a third-party request outside the Rails API.
|
||||||
|
- For blob responses, pass `responseType: 'blob'` so the wrapper does not camelCase the body.
|
||||||
|
|
||||||
|
## Imports and aliases
|
||||||
|
|
||||||
|
- The `@` alias points to `frontend/src`.
|
||||||
|
- Prefer `@/...` imports for app code instead of long relative paths.
|
||||||
|
- Keep type imports separate with `import type`.
|
||||||
|
- Match existing import grouping: external packages, app modules, then type imports.
|
||||||
|
|
||||||
|
## Tailwind and UI
|
||||||
|
|
||||||
|
- Tailwind scans `src/**/*.{html,js,ts,jsx,tsx,mdx}`.
|
||||||
|
- Use `cn` from `src/lib/utils.ts` for conditional class names and class merging.
|
||||||
|
- Reuse components from `src/components/common`, `src/components/layout`, and `src/components/ui` before adding new primitives.
|
||||||
|
- Keep Tailwind classes consistent with nearby components.
|
||||||
|
- When adding dynamic tag color classes, update `tailwind.config.js` safelist if the class cannot be statically detected.
|
||||||
|
- Do not introduce new UI libraries or production dependencies without approval.
|
||||||
|
|
||||||
|
## Lint and build constraints
|
||||||
|
|
||||||
|
- ESLint uses `@eslint/js`, `typescript-eslint`, `eslint-plugin-react-hooks`, and `eslint-plugin-react-refresh`.
|
||||||
|
- The hooks rules are enforced; fix hook ordering instead of disabling the rule.
|
||||||
|
- `react-refresh/only-export-components` is enabled as a warning with `allowConstantExport`.
|
||||||
|
- Build failures from unused locals or unused parameters are TypeScript errors, not lint-only issues.
|
||||||
|
|
||||||
|
## Files to avoid in routine work
|
||||||
|
|
||||||
|
- Do not edit `dist/` output directly.
|
||||||
|
- Do not inspect or modify `node_modules/` unless explicitly needed.
|
||||||
|
- Keep generated build artifacts out of source changes unless the user asks for them.
|
||||||
Reference in New Issue
Block a user