Skip to content

Project Table#666

Merged
lbedner merged 1 commit intomainfrom
project-table
May 3, 2026
Merged

Project Table#666
lbedner merged 1 commit intomainfrom
project-table

Conversation

@lbedner
Copy link
Copy Markdown
Owner

@lbedner lbedner commented May 2, 2026

No description provided.

Copilot AI review requested due to automatic review settings May 2, 2026 23:49
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a per-user (“multi-tenant”) Insights mode centered on a new project table, including encrypted per-project credentials and context-aware migration generation so new stacks can choose shared vs per-user Insights schema at generation time.

Changes:

  • Introduces insights_per_user option/flag across copier + service parsing, and adds Project CRUD + per-project bulk insights endpoint in the backend template.
  • Implements per-user Insights data model (Project + project_id FKs) and adds an encryption helper + ProjectService to encrypt/decrypt stored credentials.
  • Extends the migration generator to support context-driven Insights spec variants and richer alter-table operations; updates tests accordingly.

Reviewed changes

Copilot reviewed 48 out of 48 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
tests/core/test_migration_spec.py Updates legacy migration key expectations.
tests/core/test_migration_generator.py Updates migration spec tests for per-user Insights build.
tests/cli/test_stack_generation.py Adds insights_per_user stack combination coverage.
tests/cli/conftest.py Adds insights_per_user template spec.
copier.yml Adds insights_per_user copier prompt.
aegis/templates/copier-aegis-project/{{ project_slug }}/tests/test_encryption.py.jinja Adds encryption helper tests (per-user mode).
aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/test_query_service.py Seeds Project when required by schema.
aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/test_project_service.py.jinja Adds ProjectService encryption/CRUD tests.
aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/test_insights_collectors.py Updates collector tests to pass Project context.
aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/test_insight_service.py Updates InsightService tests for project scoping.
aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/test_goal_service.py.jinja Updates goal tests to use project_id FK.
aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/test_collector_service.py Updates CollectorService tests for project scoping.
aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/test_collector_reddit.py Updates Reddit collector tests for project scoping.
aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/test_collector_pypi.py Updates PyPI collector tests for project scoping.
aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/test_collector_plausible.py Updates Plausible collector tests for project scoping.
aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/test_collector_github_traffic.py Updates GitHub traffic collector tests for project scoping.
aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/test_collector_github_stars.py Updates GitHub stars collector tests for project scoping.
aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/test_collector_github_events.py Updates GitHub events collector tests for project scoping.
aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/_collector_fixtures.py Adds shared project seeding helper for collector tests.
aegis/templates/copier-aegis-project/{{ project_slug }}/tests/api/test_insights_projects_endpoints.py.jinja Adds Project CRUD + per-project insights API tests.
aegis/templates/copier-aegis-project/{{ project_slug }}/tests/api/test_insights_endpoints.py Updates API test seeding for project_id-required rows.
aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/insights/query_service.py Adds optional project scoping for bulk queries.
aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/insights/project_service.py.jinja Adds ProjectService with encrypted credential handling.
aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/insights/project_schemas.py.jinja Adds Project request/response schemas + credential masking.
aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/insights/models.py.jinja Adds Project model + per-user FKs/indexes and relationships.
aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/insights/jobs.py.jinja Updates scheduler jobs to iterate projects in per-user mode.
aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/insights/insight_service.py.jinja Adds optional project_id stamping for events.
aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/insights/goal_service.py.jinja Changes goals to use project_id instead of slug scoping.
aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/insights/goal_schemas.py.jinja Updates goal schemas for per-project routing + project_id.
aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/insights/event_service.py.jinja Adds project scoping support for user-event CRUD.
aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/insights/event_schemas.py.jinja Gates event schemas on per-user mode.
aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/insights/deps.py.jinja Adds per-user project ownership dependency helpers.
aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/insights/collectors/reddit.py.jinja Scopes dedupe + inserts by project when present.
aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/insights/collectors/pypi.py.jinja Uses project config before env vars in per-user mode.
aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/insights/collectors/plausible.py.jinja Uses project config before env vars in per-user mode.
aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/insights/collectors/github_traffic.py.jinja Uses project config before env vars in per-user mode.
aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/insights/collectors/github_stars.py.jinja Scopes existing-row/event queries by project when present.
aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/insights/collectors/github_events.py.jinja Scopes existing-row queries by project when present.
aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/insights/collectors/base.py.jinja Adds project plumbing + stamps project_id on writes.
aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/insights/collector_service.py.jinja Adds project plumbing + project-scoped cache invalidation.
aegis/templates/copier-aegis-project/{{ project_slug }}/app/core/encryption.py Adds Fernet-based encryption helper derived from SECRET_KEY.
aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/api/insights.py.jinja Adds per-project insights endpoint + Project CRUD API.
aegis/core/template_generator.py Propagates insights_per_user into template context.
aegis/core/services.py Adds per_user option to insights service spec; removes link migration.
aegis/core/migration_generator.py Adds context-aware Insights spec builder + alter-table enhancements.
aegis/core/insights_service_parser.py Parses insights[per_user] option into config.
aegis/core/copier_manager.py Passes insights_per_user into context and migration generation.
aegis/constants.py Adds AnswerKeys.INSIGHTS_PER_USER constant.
Comments suppressed due to low confidence (4)

aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/insights/deps.py.jinja:38

  • In per-user mode, writes to InsightEvent require a non-null project_id, but this provider constructs InsightService(db) without a project context. If any route/plugin uses this dep and calls add_event(), it will hit a NOT NULL violation (and reads will be unscoped). Consider providing a project-scoped InsightService dependency (based on get_owned_project) and/or preventing use of the unscoped provider in per-user builds.
async def get_insight_service(
    db: AsyncSession = Depends(get_async_db),
) -> InsightService:
    """Provide an InsightService instance."""
    return InsightService(db)

aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/insights/collectors/base.py.jinja:227

  • upsert_metric() sets project_id=self.project_id for new rows. In per-user mode that column is non-nullable, so if the collector was constructed without a project this will fail with a NOT NULL violation. Either enforce a non-null project_id for per-user collectors or guard and raise a clear error before attempting the insert.
    aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/insights/collectors/base.py.jinja:99
  • In per-user mode InsightMetric.project_id is NOT NULL, but BaseCollector still allows project=None (so project_id becomes None). This will inevitably cause integrity errors on insert. Consider requiring a Project in per-user builds (fail fast in __init__) instead of advertising a project=None fallback.
    aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/insights/insight_service.py.jinja:296
  • In per-user mode InsightEvent.project_id is non-nullable, but add_event() writes project_id=self.project_id where self.project_id may be None (default constructor). This will fail at runtime with an integrity error. Consider making project_id required in per-user builds or raising a clear exception if it’s missing.

Comment thread aegis/core/migration_generator.py Outdated
Comment thread aegis/core/migration_generator.py
Comment thread aegis/core/migration_generator.py Outdated
@lbedner lbedner merged commit c492c96 into main May 3, 2026
8 checks passed
@lbedner lbedner deleted the project-table branch May 3, 2026 01:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants