Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
.agents/
.venv
site
config.toml
*.log
*.pid
auth
api
tmp/
dist/
node_modules/
.DS_Store
.antigravitycli
9 changes: 9 additions & 0 deletions .specify/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Machine-local Spec Kit state — not meant to be shared.
# Managed by the Specify CLI; safe to edit (your changes are preserved on refresh).

# Local pointer to the current feature directory. Rewritten every time you
# switch features, so it is per-checkout state rather than something to share.
feature.json

# Per-machine extension config overrides.
extensions/*/local-config.yml
9 changes: 9 additions & 0 deletions .specify/init-options.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"ai": "agy",
"ai_skills": true,
"feature_numbering": "sequential",
"here": true,
"integration": "agy",
"script": "sh",
"speckit_version": "0.16.2.dev0"
}
15 changes: 15 additions & 0 deletions .specify/integration.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"version": "0.16.2.dev0",
"integration_state_schema": 1,
"installed_integrations": [
"agy"
],
"integration_settings": {
"agy": {
"script": "sh",
"invoke_separator": "-"
}
},
"integration": "agy",
"default_integration": "agy"
}
17 changes: 17 additions & 0 deletions .specify/integrations/agy.manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"integration": "agy",
"version": "0.16.2.dev0",
"installed_at": "2026-08-09T10:20:01.966773+00:00",
"files": {
".agents/skills/speckit-analyze/SKILL.md": "2e89ffed73764eb9d3ee2d9fba7e245a5e73229b809ddec52409ca74c44e585d",
".agents/skills/speckit-clarify/SKILL.md": "5e239a81711fb93b26a70f4384ee40461700d987245bda903c2966b4847d0e98",
".agents/skills/speckit-constitution/SKILL.md": "b1870f61afe307e96d07b1cb7adb96ad8b3c637f86a79df165690b8696916a2a",
".agents/skills/speckit-implement/SKILL.md": "248c2fa4be8a969ea771c88c38546d6735d7d4994bbe698bbabd18f53f88f0cd",
".agents/skills/speckit-converge/SKILL.md": "1355b748919c7750cc87be94534192e5ff227229c14cbd34ca993a5f977a4ce2",
".agents/skills/speckit-plan/SKILL.md": "c5522489fd177028e02ff4f1588a06bde811a0146cdc1d3495812694d6ea41b3",
".agents/skills/speckit-checklist/SKILL.md": "4eb7e030d04014e6bbf5177f84aeef19b11adfa8470a14dd18506f65c7cf9dcb",
".agents/skills/speckit-specify/SKILL.md": "fc1a68dceba9fa9317a9d7dabda4629995628dc6dcc7c80b313190141c1dee79",
".agents/skills/speckit-tasks/SKILL.md": "2dceed4345af65dbc6625157be8817dc35f2b0943b5896815ef1bc4d3421efba",
".agents/skills/speckit-taskstoissues/SKILL.md": "2c00fdc774cb9b435ea8566c7efa8b208568d533d57529e61c35f18aa52d6c67"
}
}
18 changes: 18 additions & 0 deletions .specify/integrations/speckit.manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"integration": "speckit",
"version": "0.16.2.dev0",
"installed_at": "2026-08-09T10:20:01.976252+00:00",
"files": {
".specify/scripts/bash/check-prerequisites.sh": "a7d8a14ecf87332b600cd966b5d0e7cb9d594abce7e4d1ee4372b2b5b3efff06",
".specify/scripts/bash/common.sh": "6ff86bf39f6b4684b0f80927dc7a1dadec26b4671988a3fe4d6c2523cbd3aa22",
".specify/scripts/bash/create-new-feature.sh": "ad09a94a2c1107e25e5386a834da1d7a31f9abb06ab8bfd323a7b84038221e39",
".specify/scripts/bash/setup-plan.sh": "4469b22960f43c07c33dca00de6dedb252145e9a9ce8fbb0e63be82e02b082ab",
".specify/scripts/bash/setup-tasks.sh": "cf21ba2212b4dd5b435c5ea8527500cfd27768b86c0bbc7ebc3207759f118d27",
".specify/templates/checklist-template.md": "709d8ab8384a3a49f5e0f64479f71553ef6d6f8bb4f00281b05f47837993b536",
".specify/templates/constitution-template.md": "ce7549540fa45543cca797a150201d868e64495fdff39dc38246fb17bd4024b3",
".specify/templates/plan-template.md": "7e637502d41eccf0ca672496636365691fdca62ef37b27ec07fcb412dbfa90d4",
".specify/templates/spec-template.md": "3945437fc35cd30a5b2bf7beea680337c3516826d3efa5a6b92c4a7eca1ba28e",
".specify/templates/tasks-template.md": "fc29a233f6f5a27ca31f1aa46b596af6500c627441c6e62b2bc4a1d721525842",
".specify/.gitignore": "8c908410d177a1ef3d0dee16d7ad55f2ac3333df3104c4d4adee1c9b82f1dbc1"
}
}
4 changes: 4 additions & 0 deletions .specify/memory/.constitution-template.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"sha256": "ce7549540fa45543cca797a150201d868e64495fdff39dc38246fb17bd4024b3",
"source": "core"
}
67 changes: 67 additions & 0 deletions .specify/memory/constitution.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<!--
Sync Impact Report:
- Version change: 1.0.0 -> 1.1.0
- List of modified principles:
- II. Microservice Modular Architecture -> II. Microservice Modular Architecture & Clean Code
- III. Managed Database Schema Evolution -> III. Managed Database Schema Evolution & Generic ORM
- Added sections/rules:
- Clean Architecture layer boundaries (entity, usecase, repo, controller) in Principle II
- SAGA pattern with compensation events & AMQP in Principle II
- GORM Modern Generic API (gorm.G[T]) and dual-dialect support (Postgres/MySQL) in Principle III
- Passkeys (WebAuthn) and OAuth 2.0 security constraints in Security & Privacy Constraints
- Trunk-Based Development (TBD) in Quality Assurance & Development Workflow
- Removed sections: None
- Follow-up TODOs: None
-->

# FitFeed Constitution

## Core Principles

### I. Privacy-First & Data Ownership (NON-NEGOTIABLE)
FitFeed is a self-hosted, privacy-first fitness platform. Users MUST maintain total ownership and control of their fitness activities and health metrics data. All features MUST function in a self-hosted environment without mandatory dependencies on third-party cloud services. Telemetry, external tracking, or third-party data transmission is strictly prohibited unless explicitly configured and consented to by the user.

### II. Microservice Modular Architecture & Clean Code
FitFeed functionality MUST be organized into decoupled microservices located within `services/` (`auth`, `api`, `dbm`, `web`). Each Go backend service MUST strictly adhere to Clean Architecture layering:
- `internal/entity`: Pure domain models and value objects with zero database or transport dependencies.
- `internal/usecase`: Application business logic and repository interfaces; MUST NOT import HTTP/AMQP routers or database drivers.
- `internal/repo`: Data persistence implementations using GORM Modern Generic API (`gorm.G[T](db)`).
- `internal/controller`: Inbound transport entry points (HTTP REST handlers and AMQP event/RPC consumers).

Inter-service workflows spanning multiple bounded contexts MUST utilize an asynchronous SAGA pattern with compensation events (e.g. `user.creation_failed`) to guarantee eventual consistency and rollback on failure. Direct cross-service database access outside designated migrations or services is strictly forbidden.

### III. Managed Database Schema Evolution & Generic ORM
All database schema updates MUST be implemented via version-controlled SQL migration scripts in `services/dbm` using Goose embedded directly into the Go binary (`embed.FS`). Direct manual database schema alterations or runtime auto-migrations in application code are strictly prohibited. Database queries in repositories MUST use GORM's modern Generic API (`gorm.G[T](db)`) for type safety. Schema definitions and queries MUST maintain dual-dialect compatibility (PostgreSQL 17 and MySQL).

### IV. Contract-Driven & Type-Safe Interfaces
Backend APIs MUST enforce strict type checking in Go with clearly defined contract interfaces (`contracts.go`). Frontend client applications (`services/web`) MUST be written in TypeScript with full type safety and zero unhandled type coercions. Code compilation and static checks MUST pass cleanly before code integration.

### V. Developer Environment Parity & Hot Reloading
Developer experience MUST be maintained through standard automation via the root `Makefile` and `Air` configuration. All core services MUST be launchable locally via `make dev`. Environment variables and local settings MUST be managed through template-driven configuration (`config.toml` derived from `config.toml.template`).

## Security & Privacy Constraints

FitFeed MUST uphold high security and data isolation standards:
- **Authentication**: User authentication MUST be handled securely by the `auth` service using Passkeys (WebAuthn passwordless authentication), OAuth 2.0 providers, and JWT distributed session tokens.
- **Data Protection**: Personal health measurements and activity locations MUST be protected against unauthorized access. GPS traces and sensitive user metrics MUST NOT be exposed on public endpoints without user authorization.
- **License Compliance**: FitFeed is licensed under AGPL-3.0. All code additions and third-party dependencies MUST comply with AGPL-3.0 licensing requirements.

## Quality Assurance & Development Workflow

Quality standards MUST be maintained across all services:
- **Git Workflow**: The project strictly follows Trunk-Based Development (TBD). Features and fixes MUST be developed on short-lived branches (`feat/*`, `fix/*`, `chore/*`) and merged into `main` frequently via validated Pull Requests with small, atomic commits.
- **Testing & Verification**: New endpoints and core domain logic MUST include unit or integration tests. Migrations MUST be verified against local database instances before merging (`make migrate-up` / `make migrate-down`).
- **Code Formatting**: Go code MUST strictly adhere to standard `gofmt` and `go vet` rules. Frontend code MUST adhere to ESLint/Prettier formatting standards.
- **Pull Request Approval**: PRs MUST demonstrate clean builds, passing tests, and compliance with all core principles prior to merge.

## Governance

- **Supremacy**: This constitution supersedes all informal team agreements, README guides, and project documentation.
- **Amendments**: Amendments to this constitution require a pull request specifying the rationale, version update, and Sync Impact Report.
- **Versioning Policy**:
- **MAJOR**: Backward-incompatible governance changes or redefinition/removal of core principles.
- **MINOR**: Addition of new principles, sections, or materially expanded governance rules.
- **PATCH**: Wording improvements, formatting, typo fixes, or non-semantic clarifications.
- **Compliance Review**: All feature design specifications, pull requests, and architecture plans MUST be validated against this constitution.

**Version**: 1.1.0 | **Ratified**: 2025-07-18 | **Last Amended**: 2026-08-22
195 changes: 195 additions & 0 deletions .specify/scripts/bash/check-prerequisites.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
#!/usr/bin/env bash

# Consolidated prerequisite checking script
#
# This script provides unified prerequisite checking for Spec-Driven Development workflow.
# It replaces the functionality previously spread across multiple scripts.
#
# Usage: ./check-prerequisites.sh [OPTIONS]
#
# OPTIONS:
# --json Output in JSON format
# --require-tasks Require tasks.md to exist (for implementation phase)
# --include-tasks Include tasks.md in AVAILABLE_DOCS list
# --paths-only Only output path variables (no validation)
# --help, -h Show help message
#
# OUTPUTS:
# JSON mode: {"FEATURE_DIR":"...", "AVAILABLE_DOCS":["..."]}
# Text mode: FEATURE_DIR:... \n AVAILABLE_DOCS: \n ✓/✗ file.md
# Paths only: REPO_ROOT: ... \n BRANCH: ... \n FEATURE_DIR: ... etc.

set -e

# Parse command line arguments
JSON_MODE=false
REQUIRE_TASKS=false
INCLUDE_TASKS=false
PATHS_ONLY=false

for arg in "$@"; do
case "$arg" in
--json)
JSON_MODE=true
;;
--require-tasks)
REQUIRE_TASKS=true
;;
--include-tasks)
INCLUDE_TASKS=true
;;
--paths-only)
PATHS_ONLY=true
;;
--help|-h)
cat << 'EOF'
Usage: check-prerequisites.sh [OPTIONS]

Consolidated prerequisite checking for Spec-Driven Development workflow.

OPTIONS:
--json Output in JSON format
--require-tasks Require tasks.md to exist (for implementation phase)
--include-tasks Include tasks.md in AVAILABLE_DOCS list
--paths-only Only output path variables (no prerequisite validation)
--help, -h Show this help message

EXAMPLES:
# Check task prerequisites (plan.md required)
./check-prerequisites.sh --json

# Check implementation prerequisites (plan.md + tasks.md required)
./check-prerequisites.sh --json --require-tasks --include-tasks

# Get feature paths only (no validation)
./check-prerequisites.sh --paths-only

EOF
exit 0
;;
*)
echo "ERROR: Unknown option '$arg'. Use --help for usage information." >&2
exit 1
;;
esac
done

# Source common functions
SCRIPT_DIR="$(CDPATH="" cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/common.sh"

# Get feature paths.
# In --paths-only mode this is pure resolution, so pass --no-persist to opt out
# of the feature.json write side effect (issue #3025).
if $PATHS_ONLY; then
_paths_output=$(get_feature_paths --no-persist) || { echo "ERROR: Failed to resolve feature paths" >&2; exit 1; }
else
_paths_output=$(get_feature_paths) || { echo "ERROR: Failed to resolve feature paths" >&2; exit 1; }
fi
eval "$_paths_output"
unset _paths_output

# If paths-only mode, output paths and exit (no validation)
if $PATHS_ONLY; then
if $JSON_MODE; then
# Minimal JSON paths payload (no validation performed)
if has_jq; then
jq -cn \
--arg repo_root "$REPO_ROOT" \
--arg branch "$CURRENT_BRANCH" \
--arg feature_dir "$FEATURE_DIR" \
--arg feature_spec "$FEATURE_SPEC" \
--arg impl_plan "$IMPL_PLAN" \
--arg tasks "$TASKS" \
'{REPO_ROOT:$repo_root,BRANCH:$branch,FEATURE_DIR:$feature_dir,FEATURE_SPEC:$feature_spec,IMPL_PLAN:$impl_plan,TASKS:$tasks}'
else
printf '{"REPO_ROOT":"%s","BRANCH":"%s","FEATURE_DIR":"%s","FEATURE_SPEC":"%s","IMPL_PLAN":"%s","TASKS":"%s"}\n' \
"$(json_escape "$REPO_ROOT")" "$(json_escape "$CURRENT_BRANCH")" "$(json_escape "$FEATURE_DIR")" "$(json_escape "$FEATURE_SPEC")" "$(json_escape "$IMPL_PLAN")" "$(json_escape "$TASKS")"
fi
else
echo "REPO_ROOT: $REPO_ROOT"
echo "BRANCH: $CURRENT_BRANCH"
echo "FEATURE_DIR: $FEATURE_DIR"
echo "FEATURE_SPEC: $FEATURE_SPEC"
echo "IMPL_PLAN: $IMPL_PLAN"
echo "TASKS: $TASKS"
fi
exit 0
fi

# Validate required directories and files
if [[ ! -d "$FEATURE_DIR" ]]; then
echo "ERROR: Feature directory not found: $FEATURE_DIR" >&2
echo "Run /speckit-specify first to create the feature structure." >&2
exit 1
fi

if [[ ! -f "$IMPL_PLAN" ]]; then
echo "ERROR: plan.md not found in $FEATURE_DIR" >&2
echo "Run /speckit-plan first to create the implementation plan." >&2
exit 1
fi

# Check for tasks.md if required
if $REQUIRE_TASKS && [[ ! -f "$TASKS" ]]; then
echo "ERROR: tasks.md not found in $FEATURE_DIR" >&2
echo "Run /speckit-tasks first to create the task list." >&2
exit 1
fi

# Build list of available documents
docs=()

# Always check these optional docs
[[ -f "$RESEARCH" ]] && docs+=("research.md")
[[ -f "$DATA_MODEL" ]] && docs+=("data-model.md")

# Check contracts directory (only if it exists and has files)
if [[ -d "$CONTRACTS_DIR" ]] && [[ -n "$(ls -A "$CONTRACTS_DIR" 2>/dev/null)" ]]; then
docs+=("contracts/")
fi

[[ -f "$QUICKSTART" ]] && docs+=("quickstart.md")

# Include tasks.md if requested and it exists
if $INCLUDE_TASKS && [[ -f "$TASKS" ]]; then
docs+=("tasks.md")
fi

# Output results
if $JSON_MODE; then
# Build JSON array of documents
if has_jq; then
if [[ ${#docs[@]} -eq 0 ]]; then
json_docs="[]"
else
json_docs=$(printf '%s\n' "${docs[@]}" | jq -R . | jq -s .)
fi
jq -cn \
--arg feature_dir "$FEATURE_DIR" \
--argjson docs "$json_docs" \
'{FEATURE_DIR:$feature_dir,AVAILABLE_DOCS:$docs}'
else
if [[ ${#docs[@]} -eq 0 ]]; then
json_docs="[]"
else
json_docs=$(for d in "${docs[@]}"; do printf '"%s",' "$(json_escape "$d")"; done)
json_docs="[${json_docs%,}]"
fi
printf '{"FEATURE_DIR":"%s","AVAILABLE_DOCS":%s}\n' "$(json_escape "$FEATURE_DIR")" "$json_docs"
fi
else
# Text output
echo "FEATURE_DIR:$FEATURE_DIR"
echo "AVAILABLE_DOCS:"

# Show status of each potential document
check_file "$RESEARCH" "research.md"
check_file "$DATA_MODEL" "data-model.md"
check_dir "$CONTRACTS_DIR" "contracts/"
check_file "$QUICKSTART" "quickstart.md"

if $INCLUDE_TASKS; then
check_file "$TASKS" "tasks.md"
fi
fi
Loading
Loading