Hosted oncibercultura-25-26.hyper.mediavia theHypermedia Protocol

Add Wildcard to the ListComments APIAggregate Discussions Panel: Comments from All Children

    Context

      Discussions panel currently shows comments for a single document via useDiscussionsService({targetId}) → ListComments(targetAccount, targetPath) → exact WHERE iri = :iri match. Goal: when viewing an account doc, show comments from that doc AND all its children as a flat thread list sorted by latest activity.

    Plan

      Step 1: Backend — Add GLOB support to ListComments

        File: backend/api/documents/v3alpha/comments.go

        When target_path ends with *, use GLOB matching instead of exact IRI match:

          In ListComments handler (line 152), detect wildcard: strings.HasSuffix(in.TargetPath, "*")

          If wildcard:

            Strip *, build IRI prefix manually: "hm://" + acc.String() + pathWithoutStar

            Append * to create GLOB pattern: iriPattern = iriPrefix + "*"

            Use new query qIterCommentsGlob instead of qIterComments

          If no wildcard: keep existing exact-match behavior (zero regression risk)

        New SQL query qIterCommentsGlob:

        SELECT sb.id, b.codec, b.multihash, b.data, sb.extra_attrs->>'tsid' AS tsid
        FROM (
            SELECT sb.*, ROW_NUMBER() OVER (PARTITION BY sb.extra_attrs->>'tsid' ORDER BY sb.ts DESC) rn
            FROM structural_blobs sb
            WHERE sb.type = 'Comment'
            AND sb.resource IN (SELECT id FROM resources WHERE iri GLOB :iri)
        ) sb
        JOIN blobs b ON b.id = sb.id
        WHERE sb.rn = 1
        AND sb.extra_attrs->>'deleted' IS NULL
        ORDER BY sb.ts
        

        Key diff from qIterComments= (SELECT id ...) → IN (SELECT id ... WHERE iri GLOB :iri)

        Pattern follows existing GLOB usage in backend/api/activity/v1alpha/activity.go:609.

      Step 2: Frontend — Pass wildcard target_path for account docs

        File: frontend/packages/shared/src/models/comments-resolvers.ts

        In createDiscussionsResolver (line 134), when the caller wants aggregated comments:

      Accept a new optional includeChildren?: boolean parameter

      When true, pass targetPath: hmIdPathToEntityQueryPath(id.path) + '*' (or just '*' for root docs with no path)

      File: frontend/packages/shared/src/comments-service-provider.tsx

      Extend HMListDiscussionsInput to include includeChildren?: boolean, pipe through to resolver.

      File: frontend/packages/shared/src/api-comments.ts

      Pass includeChildren from input to createDiscussionsResolver.

      Step 3: Frontend — DiscussionsPanel passes includeChildren for account docs

        File: frontend/apps/desktop/src/components/discussions-panel.tsx

        When targetDocId is an account root doc (no path or empty path), pass includeChildren: true to the Discussions component.

        File: frontend/packages/ui/src/comments.tsx

        In Discussions component:

          Accept new includeChildren?: boolean prop

          Pass to useDiscussionsService({targetId, commentId, includeChildren})

      Step 4: Grouping — reuse existing getCommentGroups

        The existing getCommentGroups in frontend/packages/shared/src/comments.ts already:

          Groups comments by reply chains (linearized threads)

          Sorts by latest updateTime (newest first)

          Counts branching replies as moreCommentsCount

        Comments from different child docs will naturally form separate groups since they have different replyParent chains. No changes needed to the grouping algorithm.

        Each HMComment already has targetAccount + targetPath fields, so the UI could optionally show which doc a comment belongs to if needed later.

    Files to modify

    Verification

      Backend: write Go test or use grpcurl to call ListComments with target_path: "/*" or target_path: "*" and verify it returns comments from child docs

      Frontend: open account root doc discussions panel, verify comments from child docs appear

      Regression: open a regular doc discussions panel, verify exact-match behavior unchanged

      Runpnpm typecheck + pnpm -F @shm/shared test run + pnpm format:write