Conversation
There was a problem hiding this comment.
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_useroption/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_idFKs) 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 constructsInsightService(db)without a project context. If any route/plugin uses this dep and callsadd_event(), it will hit a NOT NULL violation (and reads will be unscoped). Consider providing a project-scoped InsightService dependency (based onget_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()setsproject_id=self.project_idfor 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_idis NOT NULL, butBaseCollectorstill allowsproject=None(soproject_idbecomes None). This will inevitably cause integrity errors on insert. Consider requiring a Project in per-user builds (fail fast in__init__) instead of advertising aproject=Nonefallback.
aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/insights/insight_service.py.jinja:296 - In per-user mode
InsightEvent.project_idis non-nullable, butadd_event()writesproject_id=self.project_idwhereself.project_idmay be None (default constructor). This will fail at runtime with an integrity error. Consider makingproject_idrequired in per-user builds or raising a clear exception if it’s missing.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.