Changed github configs endpoint semantics + added getAll()#134
Merged
Conversation
New loosely-coupled `insights` module surfacing recurring-question groups
for project managers, backed by a rebuildable cache of AI-computed clusters.
- Entities FaqGroup/FaqQuestion/FaqDocument (UUID ids, cascade + orphanRemoval)
with FaqGroupRepository; tables via ddl-auto.
- InsightsAiClient: outbound pull to AI service POST /api/v1/insights/faq/group
(mirrors ChatAiClient); AI owns clustering + PII redaction.
- InsightsFaqService: cached reads (readOnly tx); refresh replaces the cache
from the AI result. Mappers AI->entity and entity->response DTOs.
- InsightsFaqController (PM/ADMIN only):
GET /api/v1/insights/faq overview, sorted by frequency
GET /api/v1/insights/faq/{groupId} detail (404 if missing)
POST /api/v1/insights/faq/refresh trigger AI grouping, rebuild cache
- Response DTOs match the frontend contract; document id exposes the upstream
knowledge-base reference.
- Tests: controller slice (401/403/404/200, incl. @PreAuthorize on the
coroutine endpoint via async dispatch) + service unit tests. detekt clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds a knowledge-gaps panel backend in the `insights` module, surfacing components missing runbooks/ADRs for project managers, backed by a rebuildable cache of AI-classified gaps (pull-based, uses #115). - Entities KnowledgeGap/KnowledgeGapOwner (+ KnowledgeGapSeverity enum with lowercase api mapping); missingTypes as free-form strings; tables via ddl-auto. - KnowledgeGapsAiClient: outbound pull to AI service POST /api/v1/insights/knowledge-gaps/detect (mirrors ChatAiClient). AI owns detection and sources artifacts from its own index, so no data is sent. - KnowledgeGapsService: cached reads (readOnly tx, sorted by severity then related questions); refresh replaces the cache from the AI result. Mappers AI->entity (severity + ISO timestamp parsing) and entity->response DTOs. - KnowledgeGapsController (PM/ADMIN only): GET /api/v1/insights/knowledge-gaps overview, most severe first GET /api/v1/insights/knowledge-gaps/{gapId} detail (404 if missing) POST /api/v1/insights/knowledge-gaps/refresh trigger AI classification - Response DTOs match the frontend contract; owner id exposes the upstream user reference, severity is rendered lowercase. - Distinct class/file names from the FAQ feature to keep branch merges clean. - Tests: controller slice (401/403/404/200, incl. @PreAuthorize on the coroutine endpoint via async dispatch) + service unit tests. detekt clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Aligns the FAQ backend with the AI service's /insights/faq/group endpoint
and supplies it with the questions to group.
- Add chat-module API (chat/external/ChatQuestionApi + internal impl) exposing
all user questions; new ChatMessageRepository.findAllByRole query. Keeps the
cross-module access explicit instead of reaching into the chat repo.
- InsightsFaqService.refreshFaqGroups now collects user questions and sends
them in the request (the AI service is stateless).
- AiFaqGroupingRequest carries questions [{id, text}] instead of a limit.
- Drop document url everywhere and make source nullable: the AI returns only
{id, title, source?}. Touches AiFaqDocument, FaqDocument entity,
FaqDocumentResponse and the mappers.
- Update/extend tests (question forwarding, document mapping, chat API).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…knowledge-gaps Feature/194 insights knowledge gaps
Feature/181 insights faq
Feature/source filters
Resolves conflicts between this branch's citation-persistence work and dev's independently-merged chat source/time filters (#113): the citation-enrichment stream transform and the filters-forwarding AiPromptRequest call now both run in ChatService.prompt(), and both PRs' ChatServiceTests mock setups (citationRepository, connectorConfigurationService) are combined across the shared test cases. Also makes citation artifact-id parsing fail-soft: a malformed/missing artifact_id from the AI service now degrades just that one citation (logged and dropped) instead of throwing inside the stream and killing the whole chat response, matching how an unresolvable artifact id was already handled.
Feature/citations
Generating a summary is a real LLM call, so a fresh one is only
requested from the AI service when there's no cached summary for the
artifact, or the cached one was generated from different content --
its stored hash no longer matches the artifact's current content hash.
This avoids both extremes the issue calls out: regenerating on every
click, and summarizing every artifact eagerly at ingestion time.
- New GET /api/v1/artifacts/{artifactId}/summary, backed by a new
ArtifactSummary/ArtifactSummaryCitation cache (Hibernate ddl-auto,
no migration needed).
- New ArtifactSummaryAiClient wraps the AI service's POST
/api/v1/artifacts/{artifactId}/summary.
- An artifact can be either ingested (via a connector) or directly
uploaded; both are checked through their modules' exported read-only
APIs (extended ArtifactIngestionApi with exists/getHash, implemented
the previously-empty UploadApi stub) rather than reaching into their
repositories directly.
- An artifact with no content hash on record can't be cached and is
summarized fresh on every call rather than failing.
Follows up the AI service's streaming rework (sprintstart-ai#144): the AI service no longer returns a single blocking summary response, so this endpoint now proxies its token-by-token SSE stream through to the frontend, matching ChatController/ChatService's shape and patterns. - ArtifactSummaryAiClient.summarizeStream() opens an SSE Flow (like ChatAiClient.streamPrompt), translating an `error` chunk into ArtifactSummaryAiException. - ArtifactSummaryService.getSummary() returns Flow<AiArtifactSummary StreamMessage>. A cache hit is still delivered as a stream -- a single token event carrying the whole cached text -- so the wire contract is the same shape regardless of hit/miss. A cache miss proxies the AI's real stream through, accumulating tokens/citations and persisting once the stream completes (same onCompletion pattern ChatService uses for citations). A malformed citation artifact id is now dropped from both the live stream and the cache, not just the cache -- caught by a test that only checked the cache before. - The controller's endpoint now produces text/event-stream and returns the Flow directly, mirroring ChatController.prompt(). - Removed the now-unused AiArtifactSummaryResponse/ArtifactSummary Response DTOs and ArtifactSummaryMapper -- entity building is now inlined in the service, matching how ChatService handles citations. Co-Authored-By: Claude <noreply@anthropic.com>
# Conflicts: # src/main/kotlin/com/sprintstart/sprintstartbackend/connectors/github/controller/GithubConnectorController.kt # src/main/kotlin/com/sprintstart/sprintstartbackend/connectors/github/service/GithubConnectorService.kt # src/main/kotlin/com/sprintstart/sprintstartbackend/connectors/github/service/internal/GithubIssuesService.kt # src/main/kotlin/com/sprintstart/sprintstartbackend/connectors/github/service/internal/GithubPullRequestsService.kt # src/main/kotlin/com/sprintstart/sprintstartbackend/ingestion/repository/ArtifactRepository.kt # src/test/kotlin/com/sprintstart/sprintstartbackend/github/controller/GithubConnectorControllerTest.kt # src/test/kotlin/com/sprintstart/sprintstartbackend/github/service/GithubConnectorServiceTest.kt
Uploaded artifact content (e.g. images) was read via Files.readString(UTF_8) and later reconstituted via toByteArray(UTF_8), corrupting any non-UTF-8 bytes. Content is now Base64-encoded/decoded for non-text mime types via a shared ArtifactContentCodec, gated by sourceSystem so GitHub-sourced text content is unaffected. Also removes the unused incrementDeletedCount query. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…tion GithubConnectorControllerTest's update-all tests still used pmJwt (ROLE_PM) against an endpoint that now requires ROLE_USER, and asserted the old list-shaped response instead of the single-object UpdateAllRepositoriesResponse. KnowledgeGapsServiceTest still built UserDto with the old singular `project` field. These were fixed locally but not committed before the earlier push. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Resolves the ArtifactRepository query conflict (kept both branches' additions), and fixes several git-silent merge defects surfaced by compiling/testing the result: dev's PM->USER role relaxation on GithubConnectorController being dropped for connectRepository/ updateRepository, a repoSnapshotRepository test mock left over from dead code, and the binary-upload content-corruption bug (uploaded images/PDFs were read via Files.readString(UTF_8) and corrupted on round-trip) via a new ArtifactContentCodec shared by upload read and artifact-content serving. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The dev merge silently kept dev's USER role for connect/update-all/update instead of #110's deliberate PM tightening. A three-way diff against the merge-base confirms dev never touched these lines at all (only #110 did), so the correct merge resolution is to keep #110's PM requirement, matching what was already fixed on #110's branch directly. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
A three-way diff against the merge-base confirms dev never touched the role on connect/update-all/update - only this branch deliberately tightened all three from USER to PM. update-all was missed when resolving the merge conflict on GithubUpdatesService's extraction; connect and single-repo update were already correctly PM. Now consistent across all three. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Feature/artifact upload
…oints-63 #112 already contained its own resolution of the same conflicts #110 hit against dev, so this merge mostly reconciles two independently-correct resolutions of the same issues (cosmetic wording/formatting differences, parameter ordering). Also fixes two duplicate-argument compile errors (repositoryId passed twice) that git's auto-merge introduced silently without flagging a conflict, in GithubIssuesService and GithubPullRequestsService. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ement-endpoints-63 Feature/project management endpoints 63
…ummaries Feature/91 artifact summaries
…ment-fixes Hotfix/project management fixes
…counters - Replaced JPA `@Modifying` queries in `IngestionRunRepository` with native entity increments protected by `PESSIMISTIC_WRITE` locks (`findByIdForUpdate`), preventing the database from overwriting accurate ingestion counts with stale zero-values on transaction commit. - Added `@EntityGraph` to eagerly fetch `artifactIdsToDeindex` before launching the asynchronous AI sync, fixing the silent `LazyInitializationException` crash in the detached background coroutine. - Mapped 404 Not Found from the AI service to 503 Service Unavailable in `ArtifactSummaryAiClient` to correctly trigger frontend retry logic while vectors finish indexing.
Hotfix/summary fix
The "Add project management endpoints" commit (e0e8e10) reused the projectRoles field name for the new per-project role model and, in doing so, dropped the field that used to carry a user's assigned onboarding/project-catalog roles (e.g. "Backend Developer") from GET /api/v1/admin/users and /api/v1/users/me. The underlying data and the assign/unassign endpoints were untouched, just no longer exposed, which crashed the frontend admin panel (undefined.map) since it still expects that field. Adds projectRoles back as its own field alongside the newer roles/ projectIds fields -- purely additive, nothing removed. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…re-project-roles Hotfix: restore projectRoles on GetUserResponse
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.
Related issue
Extension of #35
Short summary
Checks
Additional notes