fix: display complete ActivityPub handles in feed profiles #287

Merged
erik merged 2 commits from fix/task-b1f7c2fc-feed-handles into main 2026-10-04 13:02:45 -05:00
Owner

Summary

Fix the feed profile-card handle by deriving it from the actor username and canonical ActivityPub public origin.

Task

Task: #task-b1f7c2fc. Erik approved changing this task from investigation to implementation in both repositories. Companion site PR: erik/caradoc.com#7.

Changes

  • Supply the full handle through the public author view model and share the existing admin formatter.
  • Thread the app environment into public routes so explicit federation origins are honored.
  • Preserve stored local usernames and individual-post labels; keep missing-actor behavior and log an invalid-runtime fallback.
  • Add six HTTP regressions and docs/activitypub-feed-handles.md covering evidence, cause, and verification.
  • erikvancraddock.com remains unchanged.

Testing

  • Unit tests added/updated: all six regression cases pass; five failed before the fix.
  • Live HTML comparison verified the reported profile-card difference.
  • make dev exited with all services stopped; verification uses actual local app HTTP route tests, not a claimed interactive session.

Checklist

  • ./scripts/pre-pr.sh passes, including 500 template-site tests and the complete workspace suite.
  • Documentation updated.
  • No unrelated changes included.

Human gate

No merge or production deployment without explicit Erik approval.

## Summary Fix the feed profile-card handle by deriving it from the actor username and canonical ActivityPub public origin. ## Task Task: #task-b1f7c2fc. Erik approved changing this task from investigation to implementation in both repositories. Companion site PR: https://forge.caradoc.com/erik/caradoc.com/pulls/7. ## Changes - Supply the full handle through the public author view model and share the existing admin formatter. - Thread the app environment into public routes so explicit federation origins are honored. - Preserve stored local usernames and individual-post labels; keep missing-actor behavior and log an invalid-runtime fallback. - Add six HTTP regressions and docs/activitypub-feed-handles.md covering evidence, cause, and verification. - erikvancraddock.com remains unchanged. ## Testing - [x] Unit tests added/updated: all six regression cases pass; five failed before the fix. - Live HTML comparison verified the reported profile-card difference. - make dev exited with all services stopped; verification uses actual local app HTTP route tests, not a claimed interactive session. ## Checklist - [x] ./scripts/pre-pr.sh passes, including 500 template-site tests and the complete workspace suite. - [x] Documentation updated. - [x] No unrelated changes included. ## Human gate No merge or production deployment without explicit Erik approval.
fix: display canonical ActivityPub handles in feed profiles
All checks were successful
CI / build-lint-test (pull_request) Successful in 2m19s
e162414c76
Task: #task-b1f7c2fc
Author
Owner

Independent review — erik/slugkit#287 (e162414)

  • Task: task-b1f7c2fc.
  • Reviewed as a paired deliverable: Slugkit #287 at e162414 and Caradoc #7 at e5a14c6; both PRs are open.
  • Summary: the canonical-origin handle flow is focused, shared with the admin formatter, and preserves storage/post labels. One invalid-runtime availability regression needs correction.
  • Separate verdict for erik/slugkit#287: changes-requested. Companion verdict: changes-requested for the same independently applicable issue.

Acceptance criteria (paired deliverable)

  1. met — Slugkit's configured actor receives a canonical full handle through the author view model and profile card in Slugkit #287, commit e162414.
  2. met — Caradoc #7, commit e5a14c6, provides the same focused correction; its Caradoc-domain HTTP fixture expects @caradoc@caradoc.com. This is source verification, not a claim of production deployment.
  3. met — Both PRs add six HTTP regression cases covering the full handle, an ActivityPub origin different from website/request domains, and a non-default port.
  4. partial — Missing actor, malformed URL, and invalid enabled flag are covered, but opaque-origin runtime values escape the intended fallback and make public pages fail. See blocking issue below.
  5. met — Local username storage/validation and individual-post author labels remain unchanged; successful regression cases assert both.
  6. met — Both PRs include docs/activitypub-feed-handles.md documenting reproduction, root cause, input/storage/runtime flow, changed behavior, and verification evidence.
  7. met — Required local checks passed and review/CI status is explicit below. erikvancraddock.com remains unchanged/read-only. The original Caradoc checkout's src/styles/public.css modification is preserved and excluded from the PRs.

Criteria: 7 total, 6 met, 1 missing (partial criterion 4). Companion-PR references count toward the paired task; neither PR is required to contain the other repository's implementation.

Blocking issues (1)

  • P2 — Invalid opaque-origin configuration bypasses the logged fallback. Location: template/site/src/routes/home.ts:583-590 and template/site/src/federation/config.ts:24-26. The runtime parser accepts URL strings with opaque origins and returns the string "null"; new URL(config.publicOrigin) then throws a TypeError. The new catch handles only ActivityPubRuntimeConfigError, so this configuration error now reaches the public-route error handler instead of preserving the previous local-handle rendering.
  • Evidence: With a migrated in-memory database and configured primary actor, a focused HTTP reproduction at e162414 returned 200 for https://caradoc.com and for the existing not-a-url fallback, but 500 for mailto:actor@example.com and data:text/plain,invalid. The exception is TypeError: Invalid URL with input "null", originating in createFediverseHandle. The reproduction used the template tsconfig; an initial runner configuration error was corrected and is not a product finding.
  • Required correction in both PRs: classify/reject unsupported or opaque public origins as configuration errors (or narrowly translate this validation failure at the profile-handle boundary), retain the logged local-name fallback, and add a regression expecting HTTP 200/local handle for an opaque origin. Continue rethrowing genuinely unexpected errors; do not blanket-swallow exceptions.

Warnings (0)

  • None. The missing Caradoc CI signal is explicitly waived as recorded below, not an unwaived blocker.

Checks and human gates

  • Reviewed the updated task via native task_show once and both open PR diffs/commits. Implementation in both repositories was explicitly approved.

  • Slugkit: ./scripts/pre-pr.sh passed, including 500 template-site tests and the workspace suite, supported by /tmp/slugkit-handles-pre-pr.log. CI run #483 is green for e162414, already verified through fj actions tasks; fj pr status was not retried.

  • Caradoc: make pre-pr passed build/typecheck and 378 unit tests; npm run test:all passed 409 tests, supported by /tmp/caradoc-handles-pre-pr.log.

  • Explicit Caradoc PR CI-signal waiver: Erik approved continuing independent review without Caradoc PR CI. Follow-up task-6a726241 tracks adding PR CI. This is not a merge or deployment waiver.

  • The unsuccessful Slugkit dev-server launch is disclosed; no interactive-server or deployed-fix verification is claimed.

  • No source edits, commits, pushes, merges, deployments, or task closures were performed during review.

  • Final verdict: changes-requested; blocking_issues=1; warnings=0.

  • Next: correct the invalid-origin fallback in both PRs and rerun checks/independent review. merge_approval=waiting-human; no merge or deployment is authorized.

### Independent review — erik/slugkit#287 (e162414) - Task: **task-b1f7c2fc**. - Reviewed as a paired deliverable: [Slugkit #287](https://forge.caradoc.com/erik/slugkit/pulls/287) at `e162414` and [Caradoc #7](https://forge.caradoc.com/erik/caradoc.com/pulls/7) at `e5a14c6`; both PRs are **open**. - Summary: the canonical-origin handle flow is focused, shared with the admin formatter, and preserves storage/post labels. One invalid-runtime availability regression needs correction. - **Separate verdict for erik/slugkit#287: changes-requested.** Companion verdict: **changes-requested** for the same independently applicable issue. ### Acceptance criteria (paired deliverable) 1. **met** — Slugkit's configured actor receives a canonical full handle through the author view model and profile card in [Slugkit #287](https://forge.caradoc.com/erik/slugkit/pulls/287), commit `e162414`. 2. **met** — [Caradoc #7](https://forge.caradoc.com/erik/caradoc.com/pulls/7), commit `e5a14c6`, provides the same focused correction; its Caradoc-domain HTTP fixture expects `@caradoc@caradoc.com`. This is source verification, not a claim of production deployment. 3. **met** — Both PRs add six HTTP regression cases covering the full handle, an ActivityPub origin different from website/request domains, and a non-default port. 4. **partial** — Missing actor, malformed URL, and invalid enabled flag are covered, but opaque-origin runtime values escape the intended fallback and make public pages fail. See blocking issue below. 5. **met** — Local username storage/validation and individual-post author labels remain unchanged; successful regression cases assert both. 6. **met** — Both PRs include `docs/activitypub-feed-handles.md` documenting reproduction, root cause, input/storage/runtime flow, changed behavior, and verification evidence. 7. **met** — Required local checks passed and review/CI status is explicit below. erikvancraddock.com remains unchanged/read-only. The original Caradoc checkout's `src/styles/public.css` modification is preserved and excluded from the PRs. Criteria: **7 total, 6 met, 1 missing (partial criterion 4)**. Companion-PR references count toward the paired task; neither PR is required to contain the other repository's implementation. ### Blocking issues (1) - **P2 — Invalid opaque-origin configuration bypasses the logged fallback.** Location: `template/site/src/routes/home.ts:583-590` and `template/site/src/federation/config.ts:24-26`. The runtime parser accepts URL strings with opaque origins and returns the string `"null"`; `new URL(config.publicOrigin)` then throws a `TypeError`. The new catch handles only `ActivityPubRuntimeConfigError`, so this configuration error now reaches the public-route error handler instead of preserving the previous local-handle rendering. - Evidence: With a migrated in-memory database and configured primary actor, a focused HTTP reproduction at e162414 returned **200** for `https://caradoc.com` and for the existing `not-a-url` fallback, but **500** for `mailto:actor@example.com` and `data:text/plain,invalid`. The exception is `TypeError: Invalid URL` with input `"null"`, originating in `createFediverseHandle`. The reproduction used the template tsconfig; an initial runner configuration error was corrected and is not a product finding. - Required correction in **both** PRs: classify/reject unsupported or opaque public origins as configuration errors (or narrowly translate this validation failure at the profile-handle boundary), retain the logged local-name fallback, and add a regression expecting HTTP 200/local handle for an opaque origin. Continue rethrowing genuinely unexpected errors; do not blanket-swallow exceptions. ### Warnings (0) - None. The missing Caradoc CI signal is explicitly waived as recorded below, not an unwaived blocker. ### Checks and human gates - Reviewed the updated task via native `task_show` once and both open PR diffs/commits. Implementation in both repositories was explicitly approved. - Slugkit: `./scripts/pre-pr.sh` passed, including 500 template-site tests and the workspace suite, supported by `/tmp/slugkit-handles-pre-pr.log`. CI run **#483 is green for e162414**, already verified through `fj actions tasks`; `fj pr status` was not retried. - Caradoc: `make pre-pr` passed build/typecheck and **378 unit tests**; `npm run test:all` passed **409 tests**, supported by `/tmp/caradoc-handles-pre-pr.log`. - **Explicit Caradoc PR CI-signal waiver:** Erik approved continuing independent review without Caradoc PR CI. Follow-up **task-6a726241** tracks adding PR CI. This is not a merge or deployment waiver. - The unsuccessful Slugkit dev-server launch is disclosed; no interactive-server or deployed-fix verification is claimed. - No source edits, commits, pushes, merges, deployments, or task closures were performed during review. - **Final verdict: changes-requested; blocking_issues=1; warnings=0.** - Next: correct the invalid-origin fallback in both PRs and rerun checks/independent review. **merge_approval=waiting-human**; no merge or deployment is authorized.
Author
Owner

Review correction

Opaque runtime origins are now classified as configuration errors at the public profile-handle boundary, so mailto: and data: settings retain the logged local-name fallback instead of producing HTTP 500. Two regression cases failed before this correction; all eight handle cases now pass. ./scripts/pre-pr.sh passes, including 502 template-site tests. Independent re-review follows the new-head CI gate.

### Review correction Opaque runtime origins are now classified as configuration errors at the public profile-handle boundary, so mailto: and data: settings retain the logged local-name fallback instead of producing HTTP 500. Two regression cases failed before this correction; all eight handle cases now pass. ./scripts/pre-pr.sh passes, including 502 template-site tests. Independent re-review follows the new-head CI gate.
fix: retain public feed fallback for opaque federation origins
All checks were successful
CI / build-lint-test (pull_request) Successful in 2m11s
a1fc6cc292
Task: #task-b1f7c2fc
Author
Owner

Independent review — erik/slugkit#287 (a1fc6cc)

  • Task: task-b1f7c2fc. Reviewed updated task once, both open PR views and complete paired diffs; remote branch heads match a1fc6cc and 168fe88.
  • Separate verdict for erik/slugkit#287: approved. Companion PR independently receives approved.
  • The overall change is focused: injected runtime environment determines the federation domain, shared formatting supplies the profile-card handle, and local identity/post labels remain intact.
  • The prior blocking opaque-origin regression is corrected in both heads: publicOrigin === "null" throws ActivityPubRuntimeConfigError before the formatter, entering the logged local-name fallback. Unexpected errors are still rethrown; no blanket catch or shared parser behavior expansion. The two added HTTP regressions directly cover the previously reported 500 paths.

Acceptance criteria — paired deliverable

  1. met — Slugkit's full handle flows from canonical runtime origin through the author view model to the profile card: erik/slugkit#287, a1fc6cc.
  2. met — Caradoc receives the equivalent focused fix and its HTTP fixture expects @caradoc@caradoc.com: erik/caradoc.com#7, 168fe88. Source verification, not production deployment.
  3. met — Both PRs test complete handles, a federation origin different from website/request domains, and non-default ports.
  4. met — Both test missing actor, malformed origin, invalid enabled flag, and opaque mailto:/data: origins. Opaque normalized "null" is classified before formatting; HTTP 200, local handle, published content, and warning are asserted.
  5. met — Username storage/validation and individual-post labels are unchanged; successful HTTP cases assert stored local username and local post label. Admin formatter extraction preserves its implementation.
  6. met — Both include docs/activitypub-feed-handles.md recording reproduction, cause, actor input/storage/runtime/rendering flow, correction, and verification.
  7. met — Supplied verified local checks pass; CI/review status is explicit below. Neither paired diff changes erikvancraddock.com or the original Caradoc CSS.

Criteria: 7 total, 7 met, 0 missing; repository-specific criteria use the companion PR above.

Findings

  • Blocking issues: 0. Warnings: 0.
  • Final verdict: approved. Scope, correctness, regression coverage, error handling, and documentation satisfy the paired task.

Pipeline and human gates

  • Slugkit: supplied verified ./scripts/pre-pr.sh passes, including 502 template-site tests; build-lint-test run #484 succeeded for a1fc6cc292, verified by the parent immediately before review.
  • Caradoc: supplied verified make pre-pr passes build/typecheck and 380 unit tests; npm run test:all passes 411 tests. Missing PR CI is explicitly waived by Erik for this work; follow-up task-6a726241 tracks adding it.
  • Supporting logs: /tmp/slugkit-handles-pre-pr.log, /tmp/caradoc-handles-pre-pr.log. Checks were not rerun in this bounded review; fj pr status was not used.
  • No successful interactive-server or deployed-fix verification is claimed. No source edits, commits, pushes, merges, deployments, or task closure were performed.
  • Next: wait for explicit human merge approval. merge_approval=waiting-human; the CI waiver is not merge/deployment approval.
### Independent review — erik/slugkit#287 (a1fc6cc) - Task: **task-b1f7c2fc**. Reviewed updated task once, both open PR views and complete paired diffs; remote branch heads match `a1fc6cc` and `168fe88`. - **Separate verdict for erik/slugkit#287: approved.** Companion PR independently receives **approved**. - The overall change is focused: injected runtime environment determines the federation domain, shared formatting supplies the profile-card handle, and local identity/post labels remain intact. - The prior blocking opaque-origin regression is corrected in **both** heads: `publicOrigin === "null"` throws `ActivityPubRuntimeConfigError` before the formatter, entering the logged local-name fallback. Unexpected errors are still rethrown; no blanket catch or shared parser behavior expansion. The two added HTTP regressions directly cover the previously reported 500 paths. ### Acceptance criteria — paired deliverable 1. **met** — Slugkit's full handle flows from canonical runtime origin through the author view model to the profile card: [erik/slugkit#287](https://forge.caradoc.com/erik/slugkit/pulls/287), `a1fc6cc`. 2. **met** — Caradoc receives the equivalent focused fix and its HTTP fixture expects `@caradoc@caradoc.com`: [erik/caradoc.com#7](https://forge.caradoc.com/erik/caradoc.com/pulls/7), `168fe88`. Source verification, not production deployment. 3. **met** — Both PRs test complete handles, a federation origin different from website/request domains, and non-default ports. 4. **met** — Both test missing actor, malformed origin, invalid enabled flag, and opaque `mailto:`/`data:` origins. Opaque normalized `"null"` is classified before formatting; HTTP 200, local handle, published content, and warning are asserted. 5. **met** — Username storage/validation and individual-post labels are unchanged; successful HTTP cases assert stored local username and local post label. Admin formatter extraction preserves its implementation. 6. **met** — Both include `docs/activitypub-feed-handles.md` recording reproduction, cause, actor input/storage/runtime/rendering flow, correction, and verification. 7. **met** — Supplied verified local checks pass; CI/review status is explicit below. Neither paired diff changes erikvancraddock.com or the original Caradoc CSS. Criteria: **7 total, 7 met, 0 missing**; repository-specific criteria use the companion PR above. ### Findings - **Blocking issues: 0. Warnings: 0.** - **Final verdict: approved.** Scope, correctness, regression coverage, error handling, and documentation satisfy the paired task. ### Pipeline and human gates - Slugkit: supplied verified `./scripts/pre-pr.sh` passes, including **502 template-site tests**; **build-lint-test run #484 succeeded for a1fc6cc292**, verified by the parent immediately before review. - Caradoc: supplied verified `make pre-pr` passes build/typecheck and **380 unit tests**; `npm run test:all` passes **411 tests**. Missing PR CI is explicitly waived by Erik for this work; follow-up **task-6a726241** tracks adding it. - Supporting logs: `/tmp/slugkit-handles-pre-pr.log`, `/tmp/caradoc-handles-pre-pr.log`. Checks were not rerun in this bounded review; `fj pr status` was not used. - No successful interactive-server or deployed-fix verification is claimed. No source edits, commits, pushes, merges, deployments, or task closure were performed. - **Next:** wait for explicit human merge approval. **merge_approval=waiting-human**; the CI waiver is not merge/deployment approval.
erik merged commit cf5d21bae2 into main 2026-10-04 13:02:45 -05:00
erik deleted branch fix/task-b1f7c2fc-feed-handles 2026-10-04 13:02:45 -05:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
erik/slugkit!287
No description provided.