📚

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 page export does NOT recurse subpages unless scope=subtree.
  • A workspace export 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-13SPEC-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/*.md exist and mirror their Notion spec.
  • All 6 .cursor/rules/*.mdc exist and link to their source spec.
  • docs/CHANGELOG_AI.md has an entry for every spec version bump in the Registry.