Skip to content

Create Object API (Note/Article only for now) - #73

Open
2chanhaeng wants to merge 19 commits into
mainfrom
feat/obj-api
Open

2chanhaeng wants to merge 19 commits into
mainfrom
feat/obj-api

Conversation

@2chanhaeng

Copy link
Copy Markdown
Member

Resolve #9.

Adds an objects table (Note/Article; visibility public/unlisted/followers) with its migration.

GraphQL gains a createObject mutation for authenticated instance members, a Relay Object node, and an Actor.objects connection with totalCount.

Fedify side implements an object dispatcher at /users/{identifier}/{id} (Tombstone when deleted; followers-only objects not served) and a paginated outbox of synthetic Create activities (20 per page).

Side change: ignore mise.local.toml.

Verified with mise run check, mise run test (73 GraphQL, 3 models), and mise run dev startup.

AI Disclosure: Ideas presented by a human user were refined into a plan through Claude Code (claude-fable-5-1), and the draft plan was verified and partially modified by the user. It was implemented via Codex (gpt-6-astra), and after initial verification by Claude Code (claude-fable-5-1), it was manually reviewed, verified, and partially modified by a human.

Comment thread .gitignore Outdated
2chanhaeng added a commit that referenced this pull request Sep 12, 2026
@2chanhaeng
2chanhaeng requested a review from dodok8 September 12, 2026 13:02
Comment thread packages/graphql/src/object.ts
Comment thread packages/graphql/src/federation.ts Outdated
2chanhaeng added a commit that referenced this pull request Sep 14, 2026
Actor.objects already filters out objects whose deleted timestamp is
set, but Query.node and Query.nodes still resolve deleted Actor and
Object rows by primary key, including their relations.  Add tests that
mark one row deleted and expect node to return null and nodes to return
null at that position, while a live sibling row keeps resolving.

The tests currently fail on purpose: they define the expected contract
for a follow-up change that adds a deleted IS NULL condition to the
Actor and Object drizzleNode loaders.  LocalActor is not covered
because the localActors table has no deleted column.

The tests were generated by Claude Code at the user's direction to
address the review comment below, and the user reviewed the result.

#73 (comment)

Assisted-by: Claude Code:claude-fable-5-1
2chanhaeng added a commit that referenced this pull request Sep 14, 2026
2chanhaeng added a commit that referenced this pull request Sep 14, 2026
2chanhaeng added a commit that referenced this pull request Sep 14, 2026
The outbox previously emitted Create activities whose id pointed at
a URL that nothing served, so dereferencing it returned 404.  The
Create object dispatcher registered at /ap/creates/{id} in the
previous commit fixes that; this commit covers it with tests and
updates the outbox expectations to the new id and to the object
being referenced by IRI instead of embedded.

 -  Assert the Create URI layout from Context.getObjectUri().
 -  Dereference Create activities for public and unlisted objects and
    check their type, id, actor, object, and recipients.
 -  Reject followers-only, deleted, missing, malformed, remote-actor,
    deleted-actor, and wrong-host requests with 404, matching the
    object dispatcher.

Addresses the review comment at
#73 (comment)

The test changes were written by an AI assistant following the
reviewer's comment and the hackerspub implementation as a reference,
and were verified by the human author by running mise run test and
mise run check.

Assisted-by: Claude Code:claude-fable-5-1
@2chanhaeng
2chanhaeng requested a review from sij411 September 14, 2026 04:22
dodok8
dodok8 previously approved these changes Sep 14, 2026
@dahlia dahlia added the enhancement New feature or request label Sep 14, 2026
@dahlia dahlia added this to the DrFed 0.1.0 milestone Sep 14, 2026
@dahlia dahlia moved this from Todo to In progress in NLnet NGI0 Commons Fund (2026) Sep 14, 2026

@dahlia dahlia left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The schema currently collapses ActivityPub addressing into a single visibility label, losing information that DrFed needs to inspect and compare implementations. Please preserve the original addressing and compute implementation-specific classifications for the dashboard.

The inline comments also cover timestamp precision in pagination, outbox counts, and soft-deletion behavior across relation queries. These need fixes before merging. The proposed table layout is a suggestion; preserving the protocol data is the requirement.

Comment thread packages/models/src/schema.ts Outdated
Comment thread packages/graphql/src/federation.ts Outdated
Comment thread packages/graphql/src/builder.ts
Comment thread packages/models/src/schema.ts Outdated
Comment thread packages/models/src/schema.ts

@dahlia dahlia left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Please restore the referenced fixes to the PR branch and address the follow-up comments on outbox consistency and the resource/collection model.

Comment thread packages/models/src/schema.ts
Comment thread packages/graphql/src/federation.ts
Comment thread packages/graphql/src/object.ts
Comment thread packages/models/src/schema.ts
Comment thread packages/models/src/schema.ts
2chanhaeng added a commit that referenced this pull request Sep 16, 2026
Address the follow-up review comments on PR #73 about the
resource/collection model and outbox consistency:

 -  Drop collections.role, the collection_owner_role_key index, the
    GraphQL Collection.role field, and the 'public' collection_role
    value.  Roles now live only in actor_collection_references; the
    Public collection is identified by its fixed UUID.  Document
    ownerActorId as the lifecycle owner of a locally managed
    collection, and make Actor.outbox, followers, following, and
    featured return null when the referenced collection's owner is
    soft-deleted, matching node lookups, addressing targets, and
    collection items.
 -  Add Collection.declaredTotalItems for the totalItems a collection
    document reports, and make Collection.totalCount always count the
    locally stored, visible members instead of falling back to the
    declared value.  Document the deletion-filter policy on both
    fields and on Collection.items.
 -  Add AddressingTarget.iri so the stored recipient IRI stays readable
    after the target or its author is deleted and target becomes null.
 -  Document the Actor.outbox filtering policy: the GraphQL outbox keeps
    every stored Create activity, including those whose object is
    deleted, while the ActivityPub outbox serves only Public activities
    with live objects.  Add a regression test for the deleted-object
    case.

The unreleased migration is edited in place and its snapshot verified
with drizzle-kit generate reporting no schema changes.

The user wrote a per-review application plan for each review thread
and requested its implementation.  Codex implemented and reviewed each
plan, and the user read and verified the resulting code and confirmed
it by running `mise run check` and `mise run test`.

#73 (comment)
#73 (comment)
#73 (comment)
#73 (comment)

Assisted-by: Codex:gpt-5.6-sol
Assisted-by: Claude Code:claude-fable-5-1
@2chanhaeng
2chanhaeng requested a review from dahlia September 17, 2026 08:04

@dahlia dahlia left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Please address the remaining comments on outbox ordering, resource identity after type discovery, and objects referenced by multiple activities.

Comment thread packages/graphql/src/resource.ts Outdated
Comment thread packages/graphql/src/resource.ts Outdated
Comment thread packages/models/src/relations.ts Outdated
Comment thread mise.toml Outdated
Comment thread packages/web/src/routes/workspace/create/[instance_id]/actors.tsx Outdated
2chanhaeng added a commit that referenced this pull request Sep 17, 2026
Represent registered IRIs with stable Resource nodes and nullable typed details. Expose every referencing activity through Object.activities and compute expected classifications from the selected activity. Serialize local outbox insertions and backfill existing positions to match the ActivityPub publication order.

AI provenance: The user reviewed the feedback their PR received, drafted a plan for actual application, and requested Codex to implement it along with a Fable review loop via Claude Code. Codex implemented the supplied design and regression tests. Claude Code identified missing position backfill for existing outbox rows; Codex added the migration and upgrade test in response. The user read and reviewed the completed code, then confirmed that `mise run check` and `mise run test` were successfully executed.

#73 (comment)
#73 (comment)
#73 (comment)
#73 (comment)

Assisted-by: Codex:gpt-6-astra
Assisted-by: Claude Code:claude-fable-5
2chanhaeng added a commit that referenced this pull request Sep 17, 2026
Replace every FIXME comment in the codebase with a bare link to the
issue that tracks it, and document that rule in CONTRIBUTING.md.

 -  packages/graphql/src/auth/mail.ts: the two email localization notes
    now point at the existing web i18n issue.
 -  packages/graphql/src/actor.ts: readable username generation.
 -  packages/web/src/routes/workspace/create/[instance_id]/actors.tsx:
    result-type switch lookup tables.
 -  packages/graphql/src/federation.ts: actor key pairs dispatcher and
    inbound activity persistence.
 -  packages/models/src/schema.ts: actor deletion object policy.
 -  CONTRIBUTING.md: when leaving a FIXME comment, open an issue and put
    only the issue URL in the comment.

This applies dodok8's review suggestion on the actors.tsx FIXME (linked
below) to every FIXME comment, at the user's direction.  The user also
directed turning it into a general rule in CONTRIBUTING.md.

AI provenance: The user asked Claude Code to survey every FIXME comment
and draft an issue for each.  The user read and edited the drafts, then
directed Claude Code to file them through the GitHub CLI, replace the
comments with the issue URLs, and add the CONTRIBUTING.md rule.  Claude
Code performed those steps and verified the result with `mise run
check` (types, lint, oxfmt, hongdown, license, versions) passing.

#73 (comment)
#35
#85
#86
#87
#88
#89

Assisted-by: Claude Code:claude-fable-5-1

@dahlia dahlia left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Please fix collection pagination when items are added between page requests. I also suggest adding an index for the object-to-activities lookup.

Comment thread packages/graphql/src/resource.ts Outdated
Comment thread packages/models/src/schema.ts
Implement the [#9](#9) with Note and Article storage, authenticated createObject, Relay object queries, ActivityPub dispatch, and paginated synthetic Create activities in local actor outboxes.

AI provenance: The human user provided Fable with the scope and ideas for the implementation and had them draft a plan. The user read the draft, corrected any problematic parts, and had Astra handle the implementation. This session verified those changes and ran Claude Code with claude-fable-5 in a read-only review loop. After that, the human user read and verified.

Automated validation: mise run check; mise run test including the full build (73 GraphQL and 3 model tests); mise run dev startup and HTTP GraphQL Object introspection.

Assisted-by: Claude Code:claude-fable-5-1
Assisted-by: Codex:gpt-6-astra
Keep the pre-existing mise.local.toml ignore rule separate from the
ActivityPub object feature.

AI provenance: The user requested a Fable review loop. Codex reviewed and
committed this existing working-tree change separately after Fable noted
that it was unrelated to the feature. Codex did not author the rule.
No human manual verification was confirmed. Repository checks passed.

Assisted-by: Codex:gpt-6
- Rename `/users/<ACTOR_ID>/objects/<OBJECT_ID>` to `/users/<ACTOR_ID>/<OBJECT_ID>`
- Rename `ASObject` to `APObject`
Brand the objects.id and objects.actorId columns with the Uuid type in
@drfed/models so that Drizzle queries on the objects table require Uuid
values instead of plain strings.  Add validateUuid to @drfed/models/uuid
as a type guard and route all UUID generation and validation in
@drfed/graphql through that module instead of importing uuid directly.

Cast the actor identifier in the outbox dispatcher and the test fixture
values to Uuid, and declare the seed actor identifiers as const so they
satisfy the branded column types.  Also clarify the description of the
GraphQL Object.uuid field.

AI provenance: The human user authored and verified every code change
in this commit.  AI assistance was limited to analyzing the error
messages emitted by mise run check and to drafting this commit message.

Assisted-by: Claude Code:claude-fable-5-1
Actor.objects already filters out objects whose deleted timestamp is
set, but Query.node and Query.nodes still resolve deleted Actor and
Object rows by primary key, including their relations.  Add tests that
mark one row deleted and expect node to return null and nodes to return
null at that position, while a live sibling row keeps resolving.

The tests currently fail on purpose: they define the expected contract
for a follow-up change that adds a deleted IS NULL condition to the
Actor and Object drizzleNode loaders.  LocalActor is not covered
because the localActors table has no deleted column.

The tests were generated by Claude Code at the user's direction to
address the review comment below, and the user reviewed the result.

#73 (comment)

Assisted-by: Claude Code:claude-fable-5-1
The outbox previously emitted Create activities whose id pointed at
a URL that nothing served, so dereferencing it returned 404.  The
Create object dispatcher registered at /ap/creates/{id} in the
previous commit fixes that; this commit covers it with tests and
updates the outbox expectations to the new id and to the object
being referenced by IRI instead of embedded.

 -  Assert the Create URI layout from Context.getObjectUri().
 -  Dereference Create activities for public and unlisted objects and
    check their type, id, actor, object, and recipients.
 -  Reject followers-only, deleted, missing, malformed, remote-actor,
    deleted-actor, and wrong-host requests with 404, matching the
    object dispatcher.

Addresses the review comment at
#73 (comment)

The test changes were written by an AI assistant following the
reviewer's comment and the hackerspub implementation as a reference,
and were verified by the human author by running mise run test and
mise run check.

Assisted-by: Claude Code:claude-fable-5-1
Replace object classification enums with a canonical resource registry, ordered addressing occurrences, actor collections, observed memberships, and independently persisted Create activities. Backfill existing data while preserving previously published Create IRIs. Expose stored data and versioned expected classifications via GraphQL, and use explicit Public addressing for ActivityPub serving and outbox page/count selection.

The user provided two PR [#73](#73) implementation plans and explicitly requested persisted Create activities. Codex implemented the models, migrations, GraphQL and federation changes, and regression tests according to the plans. The user also requested an independent Claude Fable 5 review loop. Codex applied verified review fixes for resource lock contention, shared collection migrations and role references, nullable remote outboxes, and timestamp-based outbox pagination using full database precision. Claude Code reviewed the entire changes using claude-fable-5.

The user read and verified the code, and directly ran `mise test` and `mise check` to confirm they passed.

Assisted-by: Codex:gpt-6
Assisted-by: Claude Code:claude-fable-5
The user requested implementation of tests for three of the five review threads from #73 that demonstrate the issues actually exist and do not require a schema redesign:

 -  Cursor precision (#73 (comment)):
    Actor.objects and Instance.actors paginated with first: 1 over rows whose published or created time carries microseconds return only the first row, because the Date mapping truncates the cursor to milliseconds.
 -  Outbox totalItems (#73 (comment)):
    a followers-only object and a deleted object are both counted by the outbox collection while the outbox page returns nothing.
 -  Soft-deleted actors (#73 (comment)):
    objects of a deleted actor still resolve through node, nodes, and Object.actor, and the actor is still listed by Instance.actors with its objects.

The tests were generated by an AI assistant from the review threads, reviewed by the human author, and run directly with mise run test: all six new tests fail for the reasons described in the reviews and every existing test still passes.  mise run check passes.

#73 (comment)
#73 (comment)
#73 (comment)

Assisted-by: Claude Code:claude-fable-5-1
Use Temporal.Instant for all timestamptz columns and GraphQL DateTime scalars. Preserve microsecond precision in composite cursors, and provide unique tie-breakers for membership connections without overwriting cursor predicates. Filter out deleted actors and their objects across nodes, relationships, addressing targets, and observed collection items/counts. Retain addressing occurrences where the target is nullable when the referenced entity is deleted. Defer deletion propagation and record future transaction and retention policy rules.

During the review of PR [[#73](https://github.com/fedify-dev/drfed/issues/73)](https://github.com/fedify-dev/drfed/issues/73), the user wrote a 3-step review application plan that requires no schema changes. They requested Codex to implement this and then run an independent Claude Fable 5 review. Codex implemented the changes, aligned the plan with the existing resource/activity model, and added regression tests. Claude Code reviewed the changes using claude-fable-5, and Codex confirmed and fixed Claude Code's finding that direct LocalActor nodes exposed details of deleted actors.

Codex verified `mise run check`, `mise run test` (including build, 136 tests passed), no schema differences via `mise run generate:migrate`, and HTTP 200 GraphQL and frontend responses from `mise run dev --no-seed` using a temporary local `.env` file that was subsequently removed. The human user also read and reviewed the code, and verified its operation with `mise run check` and `mise run test`.

Assisted-by: Codex:gpt-6
Assisted-by: Claude Code:claude-fable-5
Replace the three migrations added on this branch since 165935e8
(add_objects, add_resources_addressing_and_activities, and
add_actor_collection_references) with a single migration generated
from the current schema on top of simplify_login_challenges.  The
resulting snapshot is structurally identical to the previous final
one.

The generated SQL is extended by hand in two places: the fixed
identifier row for the public addressing collection that
ensureResource() relies on, and registration of existing actors as
resources before their iri column is dropped so databases created from
main can still be upgraded.  The legacy backfill of objects,
collections, addressing, and Create activities is dropped along with
the two tests that exercised it, since nothing has been deployed yet
and there is no data to preserve.

The user reviewed the changes and verified them locally by running
`mise run check` and `mise run test`.

#73

Assisted-by: Claude Code:claude-fable-5-1
Address the remaining review findings on the ActivityPub resource work
in PR #73:

 -  Actor.outbox.totalCount always returned 0 because createObject never
    recorded the Create activity as an outbox member.  Add
    addActorCollectionItem() to @drfed/models and call it from
    createObject and the test seed helper, so the GraphQL collection
    reflects the same activities the ActivityPub outbox serves.
 -  Drop actors.postsCount.  Nothing read it and it drifted because it
    kept counting deleted objects; Actor.objects.totalCount already
    derives the count from objects.deleted.
 -  Hide collections owned by a deleted actor from node(), nodes(),
    addressing targets, and collection items, matching the policy that
    already hides the actor itself.  The ownerActor relation no longer
    filters deleted rows; the GraphQL owner field does so instead.
 -  Drop addressing.target and the AddressingTarget.raw field.  Nothing
    populated the column until incoming activities are persisted, so
    the field always returned null.

The unreleased squashed migration is edited in place and its snapshot
verified with drizzle-kit generate reporting no schema changes.

The user pointed out remaining issues from previous changes and
requested fixes. After reviewing the changes and identifying missing
tests, they requested their addition and verified the results locally
by running `mise run check`, `mise run test` once all tests were added.

#73

Assisted-by: Claude Code:claude-fable-5-1
Address the follow-up review comments on PR #73 about the
resource/collection model and outbox consistency:

 -  Drop collections.role, the collection_owner_role_key index, the
    GraphQL Collection.role field, and the 'public' collection_role
    value.  Roles now live only in actor_collection_references; the
    Public collection is identified by its fixed UUID.  Document
    ownerActorId as the lifecycle owner of a locally managed
    collection, and make Actor.outbox, followers, following, and
    featured return null when the referenced collection's owner is
    soft-deleted, matching node lookups, addressing targets, and
    collection items.
 -  Add Collection.declaredTotalItems for the totalItems a collection
    document reports, and make Collection.totalCount always count the
    locally stored, visible members instead of falling back to the
    declared value.  Document the deletion-filter policy on both
    fields and on Collection.items.
 -  Add AddressingTarget.iri so the stored recipient IRI stays readable
    after the target or its author is deleted and target becomes null.
 -  Document the Actor.outbox filtering policy: the GraphQL outbox keeps
    every stored Create activity, including those whose object is
    deleted, while the ActivityPub outbox serves only Public activities
    with live objects.  Add a regression test for the deleted-object
    case.

The unreleased migration is edited in place and its snapshot verified
with drizzle-kit generate reporting no schema changes.

The user wrote a per-review application plan for each review thread
and requested its implementation.  Codex implemented and reviewed each
plan, and the user read and verified the resulting code and confirmed
it by running `mise run check` and `mise run test`.

#73 (comment)
#73 (comment)
#73 (comment)
#73 (comment)

Assisted-by: Codex:gpt-5.6-sol
Assisted-by: Claude Code:claude-fable-5-1
Represent registered IRIs with stable Resource nodes and nullable typed details. Expose every referencing activity through Object.activities and compute expected classifications from the selected activity. Serialize local outbox insertions and backfill existing positions to match the ActivityPub publication order.

AI provenance: The user reviewed the feedback their PR received, drafted a plan for actual application, and requested Codex to implement it along with a Fable review loop via Claude Code. Codex implemented the supplied design and regression tests. Claude Code identified missing position backfill for existing outbox rows; Codex added the migration and upgrade test in response. The user read and reviewed the completed code, then confirmed that `mise run check` and `mise run test` were successfully executed.

#73 (comment)
#73 (comment)
#73 (comment)
#73 (comment)

Assisted-by: Codex:gpt-6-astra
Assisted-by: Claude Code:claude-fable-5
Replace every FIXME comment in the codebase with a bare link to the
issue that tracks it, and document that rule in CONTRIBUTING.md.

 -  packages/graphql/src/auth/mail.ts: the two email localization notes
    now point at the existing web i18n issue.
 -  packages/graphql/src/actor.ts: readable username generation.
 -  packages/web/src/routes/workspace/create/[instance_id]/actors.tsx:
    result-type switch lookup tables.
 -  packages/graphql/src/federation.ts: actor key pairs dispatcher and
    inbound activity persistence.
 -  packages/models/src/schema.ts: actor deletion object policy.
 -  CONTRIBUTING.md: when leaving a FIXME comment, open an issue and put
    only the issue URL in the comment.

This applies dodok8's review suggestion on the actors.tsx FIXME (linked
below) to every FIXME comment, at the user's direction.  The user also
directed turning it into a general rule in CONTRIBUTING.md.

AI provenance: The user asked Claude Code to survey every FIXME comment
and draft an issue for each.  The user read and edited the drafts, then
directed Claude Code to file them through the GitHub CLI, replace the
comments with the issue URLs, and add the CONTRIBUTING.md rule.  Claude
Code performed those steps and verified the result with `mise run
check` (types, lint, oxfmt, hongdown, license, versions) passing.

#73 (comment)
#35
#85
#86
#87
#88
#89

Assisted-by: Claude Code:claude-fable-5-1
Object.activities filters activities by the referenced object and orders them by published ASC, id ASC, but the only secondary index on activities started with actorId.  Add activity_object_published_index on (objectId, published, id) together with its migration.  The same index also serves the ON DELETE CASCADE lookup on activities.objectId, which PostgreSQL does not index on its own.  A regression test checks the index definition in a freshly migrated database.

The user planned how to apply the reviews and used Claude Code to write regression tests. Afterward, they blocked the agent's access to the tests and had the plan implemented using the Codex implementation and Claude review loop. Finally, the user reviewed the changes and confirmed that `mise run check` and `mise run test` passed.

#73 (comment)

Assisted-by: Codex:gpt-5.6-sol
Assisted-by: Claude Code:claude-fable-5-1
Collection.items used an offset cursor.  Local outbox entries are prepended with min(position) - 1, so creating a post between two page requests shifted the offsets and the next page repeated an item.

Use resolveCursorConnection with an opaque base64 cursor over the stored (position, itemId) ordering and query past that boundary. position is nullable, so the predicates treat NULL positions as a separate range that sorts last instead of dropping those rows, and last/before returns edges in the same order as first/after.  Malformed cursors are reported to clients as validation errors.

Regression tests cover a post created between page requests, NULL positions with an item prepended in the middle of a walk, and backward paging.

The user planned how to apply the reviews and used Claude Code to write regression tests. Afterward, they blocked the agent's access to the tests and had the plan implemented using the Codex implementation and Claude review loop. Finally, the user reviewed the changes and confirmed that `mise run check` and `mise run test` passed.

#73 (comment)

Assisted-by: Codex:gpt-5.6-sol
Assisted-by: Claude Code:claude-fable-5-1

@dahlia dahlia left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Sorry for the additional review rounds. Please preserve the configured protocol when generating IRIs and make resource lookups independent of how the request origin is written.

const published = Temporal.Now.instant();
const id = uuid();
const fedCtx = ctx.federation.createContext(
new URL(`https://${actor.host}`),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Could we preserve ctx.rootOrigin.protocol here, as actor generation already does? With the root origin set to http://drfed.org, I reproduced createObject returning HTTPS IRIs for both the object and its Create activity. On an HTTP-only development deployment, those IRIs point to a TLS endpoint that is not served.

Please compose this context's origin from the configured protocol and the actor's stored authority, preserving any port. A regression test should create an object under an HTTP root origin, verify the object and activity IRIs, and fetch both through their advertised URLs.

if (!validateUuid(id)) return null;
const activity = await db.query.activities.findFirst({
where: {
resource: { iri: ctx.getObjectUri(Create, { id }).href },

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

These resource lookups depend on how the incoming origin is written. I reproduced both the object and Create dispatchers returning 404 Not Found when the hostname has a trailing dot, although their canonical HTTPS URLs return 200 OK. For the same host without the dot, changing the request scheme to HTTP leaves the object reachable but makes Create return 404 Not Found because this reconstructed IRI no longer matches the stored HTTPS IRI. That also affects a TLS-terminating proxy forwarding HTTP to DrFed.

Could both dispatchers apply canonicalizeAuthority(ctx.host), as findLocalActor() already does? For Create, please look up the activity by its ID within that local instance rather than by an IRI reconstructed from the request. Keep the instance restriction so another host cannot resolve it, and retain the stored canonical IRI in the response. Please cover trailing-dot hosts and an HTTP request for a stored HTTPS activity in regression tests.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

Status: In progress

Development

Successfully merging this pull request may close these issues.

GraphQL API for creating objects

4 participants