SPEC-STV-12-Comments-Activity
SPEC-STV-12 · Spec header. Spec ID: SPEC-STV-12 · Title: Comments, Activity, Import/Export, Testing, Docs, CHANGELOG · Version: 1.0.0 · Status: Planned · Authority: Reference · Priority: P1 · Owner role: Docs lead · Reviewers: Backend architect, Frontend lead, Security lead · Last reviewed: 2026-05-11 · Sync targets: app/Services/Activity/**, app/Services/Comments/**, app/Services/Import/**, app/Services/Export/**, docs/CHANGELOG_AI.md, .cursor/rules/** · Depends on: SPEC-STV-HUB, SPEC-STV-02, SPEC-STV-11 · Consumed by: every other spec (audit, tests, changelog) · Conflict rule: Hub wins. · Change policy: Docs lead + 1 reviewer; Registry bump.
1 · Comments & mentions
1.1 Model
A comment is { workspace_id, page_id, block_id?, parent_comment_id?, author_id, body (Markdown), body_html (sanitized), resolved_at, resolved_by }. Threads are bounded to a single block or a single page; replies use parent_comment_id.
1.2 Mentions
@user and @page mentions are extracted by CommentService at write time and persisted to mentions. Each new mention enqueues SendMentionNotificationJob (email + in-app).
1.3 Resolve
A comment thread is resolved by anyone with comment.update. Resolved threads hide by default; toggle to show.
1.4 API
GET /pages/{uuid}/comments, POST /comments, POST /comments/{id}/resolve, DELETE /comments/{id}. See SPEC-STV-03 §8.
2 · Activity & audit log
2.1 Schema
activity_logs (see SPEC-STV-02 §3.20).
2.2 Actions recorded
page.created, page.updated, page.archived, page.restored, page.moved, block.created, block.updated, block.deleted, comment.created, comment.resolved, share.granted, share.revoked, share_link.created, share_link.revoked, member.invited, member.role_changed, member.removed, file.uploaded, file.deleted, ai.transform.applied, template.used, template.saved, version.restored, settings.updated, rag.reindex.queued, secret_pattern.dropped.
2.3 Retention
Workspace setting activity.retention_days (default 365). A nightly job prunes older rows except member.* and share* events (kept forever for legal trail).
2.4 API
GET /workspaces/{uuid}/activity?entity=page&entity_id={uuid}&cursor=…. Filament admin surfaces the full feed.
3 · Import
3.1 Formats
- Markdown — single file or zip of folder; folder structure becomes page tree.
- HTML — sanitized + converted to block JSON.
- CSV — imports into a database; first row = property names; types inferred (
date,number,select,text).
- DOCX / PDF text extraction — P5+.
3.2 Flow
POST /imports with the file + target. The job ImportFileJob runs through parsers, creates pages/databases inside a transaction, then queues IndexRagSourceJobs. A summary row is emitted to activity_logs.
4 · Export
4.1 Formats
- Markdown (one file per page, folder mirrors tree).
- PDF (rendered server-side from HTML via headless Chromium).
- HTML (static site bundle).
- JSON (full structural dump: pages, blocks, databases, properties, rows, cell_values).
4.2 Flow
POST /exports with { scope: "page|subtree|workspace", target_format }. ExportPageJob renders to a ZIP, writes to S3, returns a signed URL by email + UI download. Exports are not real-time — expect 30 s to a few minutes for a workspace export.
4.3 Scope rules
- A
pageexport does NOT recurse subpages unlessscope=subtree.
- A
workspaceexport includes pages, databases, templates created by the workspace, files (signed-URL manifest, not embedded blobs by default), comments, activity_logs (last 90 days), settings.
5 · Test plan (full)
5.1 Layers
Feature (HTTP + DB), Unit, Policy, API contract, Browser (Dusk, optional), Queue.
5.2 Mandatory tests
- Workspaces — create, invite, role change, member remove, delete (soft + hard).
- Pages — CRUD, archive, restore, move (parent change + path rewrite), favorites, version restore.
- Blocks — add, update, move (cross-page + within page), delete, batch update, content size cap.
- Databases — create, property add/change/delete, row CRUD, cell update, view CRUD, filter + sort apply, group by select/status.
- Sharing — grant per-user, revoke, public link create + redeem + revoke, password-gated link.
- AI — transform happy path, preview-gate enforcement (no auto-apply), rate-limit denial, RAG citation present, secret-pattern refusal.
- RAG — indexed within 60 s, query returns citations, disabled-flag returns empty, secret-pattern drop logged.
- Search — returns pages/blocks/files/databases/comments/templates, permission-filtered, paginated.
- Comments — CRUD, mention notification queued, resolve.
- Activity — every mutating endpoint writes an activity row.
- Files — presign + commit, signed-URL freshness, MIME blocking, size cap.
- Policies — viewer cannot edit, commenter cannot create block, IDOR refused, archived page is read-only.
- API contract — OpenAPI snapshot, pagination meta shape, ISO timestamps, signed URLs.
5.3 Tooling
Pest 3, Laravel HTTP/DB factories, Mockery for providers, Saloon mocks for AI/Embeddings, Meilisearch test container, S3 fake (Flysystem in-memory).
6 · Docs plan (full)
6.1 Mandatory docs/*.md
See SPEC-STV-HUB §9. Each file mirrors the matching Notion spec and carries the same SoT header as a YAML front-matter block.
6.2 .cursor/rules/*.mdc
project-overview.mdc— vision + lock + non-goals (mirrors SPEC-STV-00).
database.mdc— conventions + key indexes + JSON shapes (mirrors SPEC-STV-02).
editor.mdc— block types + autosave + version protocol (mirrors SPEC-STV-04).
security.mdc— threat model + sanitization + signed URLs + rate limits (mirrors SPEC-STV-11).
rag.mdc— sources + chunking + retrieval + secret exclusion (mirrors SPEC-STV-07).
mobile.mdc— breakpoints + mobile editor adaptations + performance budget (mirrors SPEC-STV-10) and the full mobile gesture / text-selection / AI-preview / bottom-sheet / slash-drawer / haptics / a11y rule set (mirrors SPEC-STV-13 → SPEC-STV-13). The rule file embeds both spec headers as YAML front-matter and links back to the Notion sources.
6.3 Generators
php artisan docs:sync regenerates <!-- AUTO-GENERATED --> regions inside the mirrored docs from the live database (project map, schema dump, route list).
7 · CHANGELOG_AI format
docs/CHANGELOG_AI.md is append-only and line-formatted:
2026-05-11 | SPEC-STV-HUB | Product architect | 1.0.0 | Initial StevoApp pack created.
2026-05-11 | SPEC-STV-00..12 | various | 1.0.0 | All 13 sub-specs landed as Planned.
2026-05-12 | SPEC-STV-02 | Database architect | 1.0.1 | Added value_date index on database_cell_values.
2026-05-13 | SPEC-STV-08 | AI workflow lead | 1.1.0 | Added `translate` action; default model = gpt-4.1.Fields: date | Spec ID(s) | author role | semver | one-line summary.
CI step changelog-ai-lint checks: monotonically non-decreasing dates, valid semver, valid spec IDs against docs/SPEC_REGISTRY.md, and that every Architecture-tier or Constitutional change has an entry.
8 · Acceptance criteria
- Comments + mentions work end-to-end; notifications fire.
- Every state-changing endpoint writes an activity row.
- Import handles a 100-file Markdown folder under 60 s for typical sizes.
- Export of a 200-page workspace completes under 5 min.
- Pest suite green; policy tests green; API contract snapshot green.
- All 13
docs/*.mdexist and mirror their Notion spec.
- All 6
.cursor/rules/*.mdcexist and link to their source spec.
docs/CHANGELOG_AI.mdhas an entry for every spec version bump in the Registry.