2de7e13a8a
#346 Co-authored-by: miteruzo <miteruzo@naver.com> Reviewed-on: #347
148 lines
6.3 KiB
Markdown
148 lines
6.3 KiB
Markdown
# 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.
|