Skip to content

Changed github configs endpoint semantics + added getAll()#134

Merged
Tanzkalmar35 merged 74 commits into
devfrom
feature/get-all-repo-configs
Jul 19, 2026
Merged

Changed github configs endpoint semantics + added getAll()#134
Tanzkalmar35 merged 74 commits into
devfrom
feature/get-all-repo-configs

Conversation

@Tanzkalmar35

Copy link
Copy Markdown
Collaborator

Related issue

Extension of #35

Short summary

  • Added a GET endpoint for retrieving all configs.
  • Small semantic change - PUT /api/v1/github/config/global is now /api/v1/github (the same without '/global'), GET the same

Checks

  • I verified the code makes sense intuitively
  • The PR changes affect only this issue, no unrelated/unwanted code changes to other modules/code segments
  • CI runs (./gradlew clean build, keycloack)
  • New business logic is unit tested, including WebMvcTest for api controllers
  • The new functionality is tested manually

Additional notes

VladyslavHandzha and others added 30 commits July 4, 2026 22:28
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>
kiranfin and others added 26 commits July 13, 2026 23:06
…knowledge-gaps

Feature/194 insights knowledge gaps
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.
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>
…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
…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.
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

@VladyslavHandzha VladyslavHandzha left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

lgtm

@Tanzkalmar35
Tanzkalmar35 merged commit e5849fb into dev Jul 19, 2026
4 checks passed
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.

7 participants