Skip to content

Commit ca07a52

Browse files
committed
docs(readme): fix clientId URL trailing slash inconsistency
1 parent 2a98b05 commit ca07a52

2 files changed

Lines changed: 3 additions & 1 deletion

File tree

.beads/issues.jsonl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
{"id":"hypercerts-sdk-bub.1","title":"Use isValidUri in imageToUrl to pass through all valid URI schemes instead of only http(s)","description":"## Files\n- packages/sdk-core/src/repository/ProfileOperationsImpl.ts (modify)\n- packages/sdk-core/tests/repository/ProfileOperationsImpl.test.ts (modify)\n\n## What to do\n\n### In ProfileOperationsImpl.ts\n\n1. Add import for `isValidUri` from `../lib/url-utils.js` (line ~12 area, alongside existing imports)\n\n2. Replace the current scheme check in `imageToUrl` (lines 111-113):\n ```typescript\n // BEFORE (remove this):\n if (result.startsWith(\"http://\") || result.startsWith(\"https://\")) {\n return result;\n }\n\n // AFTER (replace with):\n if (isValidUri(result)) {\n return result;\n }\n ```\n\n This reuses the existing `isValidUri` function from `src/lib/url-utils.ts` which matches any valid URI scheme per RFC 3986 (uses regex `/^[a-zA-Z][a-zA-Z0-9+\\-.]*:/` and the native URL constructor). It already handles http, https, ipfs, at, data, and any other valid scheme.\n\n3. Keep everything else in `imageToUrl` unchanged:\n - The `extractCidFromImage(image)` call\n - The falsy check that throws `Error(\"Unable to extract CID or URI from image record\")`\n - The fallthrough to `getBlobUrl(this.pdsUrl, this.repoDid, result)` for bare CIDs\n\n### In ProfileOperationsImpl.test.ts\n\n4. Add a test case in the `getCertifiedProfile` describe block (after the existing \"should handle URI image format\" test around line 152) that verifies non-http URI schemes are passed through unchanged:\n\n ```typescript\n it(\"should pass through non-http URI schemes unchanged (e.g., ipfs://)\", async () =\u003e {\n mockAgent.getProfile!.mockResolvedValue({\n success: true,\n data: { handle: \"test.bsky.social\" },\n });\n\n mockAgent.com.atproto.repo.getRecord.mockResolvedValue({\n success: true,\n data: {\n value: {\n $type: CERTIFIED_PROFILE_COLLECTION,\n createdAt: \"2024-01-01T00:00:00.000Z\",\n displayName: \"Test\",\n avatar: {\n $type: \"org.hypercerts.defs#uri\",\n uri: \"ipfs://QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG\",\n },\n banner: {\n $type: \"org.hypercerts.defs#uri\",\n uri: \"ar://some-arweave-tx-id\",\n },\n },\n },\n });\n\n const result = await profileOps.getCertifiedProfile();\n expect(result).not.toBeNull();\n expect(result!.avatar).toBe(\"ipfs://QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG\");\n expect(result!.banner).toBe(\"ar://some-arweave-tx-id\");\n });\n ```\n\n## Dont\n- Do NOT change `extractCidFromImage` or `getBlobUrl` — those are correct as-is\n- Do NOT change the error message or error type for the falsy check\n- Do NOT add a new URI validation function — reuse `isValidUri` from `../lib/url-utils.js`\n- Do NOT change any other method in ProfileOperationsImpl\n- Do NOT modify the `isValidUri` function itself","acceptance_criteria":"1. `pnpm --filter @hypercerts-org/sdk-core test ProfileOperationsImpl` passes — all existing tests still pass\n2. The new test \"should pass through non-http URI schemes unchanged\" passes\n3. `pnpm --filter @hypercerts-org/sdk-core build` succeeds\n4. `pnpm --filter @hypercerts-org/sdk-core lint` passes\n5. In the source, `imageToUrl` calls `isValidUri(result)` instead of checking `startsWith(\"http\")` / `startsWith(\"https\")`\n6. `isValidUri` is imported from `../lib/url-utils.js`\n7. No new utility functions were created","status":"closed","priority":2,"issue_type":"task","assignee":"kzoeps","owner":"[email protected]","estimated_minutes":30,"created_at":"2026-02-16T12:35:54.50661348+06:00","created_by":"kzoeps","updated_at":"2026-02-16T14:25:22.123150145+06:00","closed_at":"2026-02-16T14:25:22.123150145+06:00","close_reason":"9eb7015 Use isValidUri to pass through all valid URI schemes in imageToUrl","labels":["scope:trivial"],"dependencies":[{"issue_id":"hypercerts-sdk-bub.1","depends_on_id":"hypercerts-sdk-bub","type":"parent-child","created_at":"2026-02-16T12:35:54.507982699+06:00","created_by":"kzoeps"}]}
2020
{"id":"hypercerts-sdk-c13","title":"Add JSDoc documentation for collection avatar/banner","description":"Add JSDoc documentation to createCollection() and updateCollection() methods about avatar field. Add usage examples in method documentation showing avatar in collections and projects.","notes":"## Source\nFrom: specs/lexicon-sync/v0.10.0-beta.4-v0.10.0-beta.11.md (Change 3)\nCHANGELOG: PR #106 - Add avatar and banner fields to collection lexicon\n\n## What Changed\n- Collections now have avatar and banner fields for visual representation\n- These are image fields (Uri, SmallImage, or LargeImage)\n\n## Implementation Status\n- [x] Verify CreateCollectionParams supports avatar/banner\n- [x] Verify createCollection/updateCollection handle fields\n- [ ] Add JSDoc documentation about avatar (THIS TASK)\n- [ ] Add usage examples for avatar in collections and projects\n- [x] Tests complete\n\n## Validation Checklist\n- [ ] Format check passes (pnpm format:check)\n- [ ] Lint passes (pnpm lint)\n- [ ] Typecheck passes (pnpm typecheck)\n- [ ] Build passes (pnpm build)\n- [ ] Tests pass (pnpm test)\n\n## Changeset\n- Type: minor (new feature available)\n- Already created\n\nNote: Method documentation mentions banner but not avatar\n\nIMPORTANT: Keep this issue in sync with the source .md file.","status":"closed","priority":2,"issue_type":"task","owner":"[email protected]","created_at":"2026-01-27T16:47:16.053509722+13:00","created_by":"Adam Spiers","updated_at":"2026-01-28T10:52:01.615872728+13:00","closed_at":"2026-01-28T10:52:01.615872728+13:00","close_reason":"Added comprehensive JSDoc documentation with avatar/banner examples to createCollection, updateCollection, createProject, and updateProject methods"}
2121
{"id":"hypercerts-sdk-d2e","title":"Add tests for location string format","description":"Add explicit tests verifying location string format works (e.g., 'New York, NY, USA' as location value).","notes":"Follow-up from hypercerts-sdk-m7h (beta.13 location string format support).\n\nThe implementation already works - this adds explicit test coverage.\n\nTest cases to add in packages/sdk-core/tests/repository/HypercertOperationsImpl.test.ts:\n- createLocationRecord with string location value\n- attachLocation with inline string location\n- Verify string gets wrapped in URI ref format","status":"closed","priority":3,"issue_type":"task","owner":"[email protected]","created_at":"2026-01-29T14:38:14.006311332+13:00","created_by":"Adam Spiers","updated_at":"2026-01-29T15:18:11.946123637+13:00","closed_at":"2026-01-29T15:18:11.946123637+13:00","close_reason":"Added tests for simple text string location format in attachLocation and createCollection"}
22+
{"id":"hypercerts-sdk-eww","title":"Epic: Resolve CodeRabbit review for PR #131","description":"Resolve remaining open CodeRabbit inline review comment on PR #131. 1 comment in packages/sdk-core/README.md about clientId URL form inconsistency (missing trailing slash).","status":"closed","priority":3,"issue_type":"epic","owner":"karma.gainforest.id","created_at":"2026-02-20T15:19:18.075148138+06:00","created_by":"karma.gainforest.id","updated_at":"2026-02-20T15:21:28.32000638+06:00","closed_at":"2026-02-20T15:21:28.32000638+06:00","close_reason":"45a460d All child tasks complete: trailing slash fix applied","labels":["scope:trivial"]}
23+
{"id":"hypercerts-sdk-eww.1","title":"Fix clientId URL trailing slash inconsistency in README","description":"## Files\n- packages/sdk-core/README.md (modify)\n\n## What to do\nLine 131 contains a manually-constructed clientId example URL: `http://localhost?scope=...`\nLine 141 recommends using `http://localhost/` (with trailing slash).\n\nThese are inconsistent. `http://localhost?...` resolves to an empty path, while `http://localhost/` has an explicit root path. Some AT Protocol authorization servers may normalize or validate them differently.\n\nFix: On line 131, change `http://localhost?scope=` to `http://localhost/?scope=` (add trailing slash before the query string).\n\nCodeRabbit comment: https://github.com/hypercerts-org/hypercerts-sdk/pull/131#discussion_r2831500873\n\n## Don't\n- Change any other URLs in the README\n- Modify any code files\n- Change the query parameters or their encoding\n- Touch lines 141-142 (they are already correct)","acceptance_criteria":"1. Line 131 of packages/sdk-core/README.md contains `http://localhost/?scope=` (with trailing slash before query string)\n2. Lines 141-142 are unchanged\n3. No other files are modified\n4. pnpm build succeeds","status":"closed","priority":3,"issue_type":"task","assignee":"karma.gainforest.id","owner":"karma.gainforest.id","estimated_minutes":10,"created_at":"2026-02-20T15:19:28.823599913+06:00","created_by":"karma.gainforest.id","updated_at":"2026-02-20T15:21:06.010913316+06:00","closed_at":"2026-02-20T15:21:06.010913316+06:00","close_reason":"45a460d fix clientId URL trailing slash in README","labels":["scope:trivial"],"dependencies":[{"issue_id":"hypercerts-sdk-eww.1","depends_on_id":"hypercerts-sdk-eww","type":"parent-child","created_at":"2026-02-20T15:19:28.825105507+06:00","created_by":"karma.gainforest.id"}]}
2224
{"id":"hypercerts-sdk-fi6","title":"Add RichText utility for creating facets from text","description":"Create a utility function that uses @atproto/api's RichText class to automatically detect and create facets (mentions, links, hashtags) from plain text. This allows users to write natural text like 'Led by @alice with support from https://example.org #sustainability' and have facets auto-generated. Export this as a helper function from the SDK.","notes":"## Source\nFrom: specs/lexicon-sync/v0.10.0-beta.4-v0.10.0-beta.11.md (Change 2)\nCHANGELOG: PR #91 - Add rich text facet support to activity claim descriptions\n\n## What Changed\n- Added shortDescriptionFacets and descriptionFacets fields to activity lexicon\n- Supports mentions, URLs, hashtags, etc. in activity descriptions\n\n## ✅ COMPLETED\n\n### Implementation\nCreated RichText utility in `src/lib/rich-text.ts`:\n- `createFacetsFromText(text, agent?)` - async, resolves mentions if agent provided\n- `createFacetsFromTextSync(text)` - sync, fast detection without mention resolution\n- Re-exports `RichText` class from @atproto/api for advanced usage\n- Exports `RichTextResult` and `AppBskyRichtextFacet` types\n\n### Exports added to index.ts\n- `createFacetsFromText`\n- `createFacetsFromTextSync`\n- `RichText`\n- `RichTextResult` (type)\n- `AppBskyRichtextFacet` (type)\n\n### Tests\nAdded 11 tests in `tests/lib/rich-text.test.ts`:\n- URL detection\n- Hashtag detection\n- Mention detection (without resolution)\n- Multiple facet types\n- Plain text handling\n- Empty text handling\n- Byte index calculation\n- Async version\n- Hypercert description example\n- RichText class export\n- Segment iteration\n\n## Validation\n- [x] Format check passes\n- [x] Lint passes\n- [x] Typecheck passes\n- [x] Build passes (with unrelated attachment warnings)\n- [x] Tests pass (11/11)\n- [x] RichText utility is exported correctly\n\n## Changeset\n- Type: minor (new feature available)\n- TODO: Create changeset file\n\nIMPORTANT: Keep this issue in sync with the source .md file.","status":"closed","priority":2,"issue_type":"task","owner":"[email protected]","created_at":"2026-01-27T16:47:14.717746859+13:00","created_by":"Adam Spiers","updated_at":"2026-01-28T10:48:19.158564312+13:00","closed_at":"2026-01-28T10:48:19.158574762+13:00"}
2325
{"id":"hypercerts-sdk-g7q","title":"Test pattern inconsistency: some loopback tests check for absence of warnings","description":"The loopback client_id auto-generation tests have an inconsistency in how they verify warnings.\n\nInconsistent pattern:\n- Test http://localhost/ (lines 327-361): Explicitly checks that NO rewrite warning is emitted\n- Test http://localhost (lines 296-325): Does NOT check for absence of warning\n- Test http://127.0.0.1 (lines 363-397): Explicitly checks that rewrite warning IS emitted\n\nThe test for http://localhost/ includes an assertion to verify NO rewrite warning, but the test for http://localhost (without trailing slash) does not check for absence of warning, even though it should also not emit a warning according to the implementation (OAuthClient.ts lines 202-210).\n\nThis inconsistency makes the test suite harder to understand and maintain.\n\nAcceptance criteria:\n- Review all loopback tests for consistent warning assertions\n- Add explicit warning checks to http://localhost test (should be undefined)\n- Ensure all tests that should NOT warn explicitly verify no warning\n- Ensure all tests that SHOULD warn explicitly verify warning is present\n- Document the expected warning behavior in test comments\n- All tests pass","status":"open","priority":3,"issue_type":"task","owner":"[email protected]","created_at":"2026-02-20T14:52:00.510914501+06:00","created_by":"kzoeps","updated_at":"2026-02-20T14:52:00.510914501+06:00"}
2426
{"id":"hypercerts-sdk-h0l","title":"Update changeset to mark BlobOperations constructor change as breaking","description":"Constructor signature change (HypercertOperationsImpl/ProfileOperationsImpl now require BlobOperations) should be marked as breaking with minor bump for 0.x semantics.","notes":"Source: PR #122 CodeRabbit review comment on .changeset/fix-sds-endpoint-routing.md\n\nChange from patch to minor and add BREAKING note:\n- @hypercerts-org/sdk-core: minor (not patch)\n- Add: **BREAKING:** HypercertOperationsImpl/ProfileOperationsImpl constructors now require a BlobOperations instance instead of a server URL.","status":"closed","priority":1,"issue_type":"task","owner":"[email protected]","created_at":"2026-01-29T14:24:14.324265145+13:00","created_by":"Adam Spiers","updated_at":"2026-01-29T14:43:09.26272051+13:00","closed_at":"2026-01-29T14:43:09.26272051+13:00","close_reason":"Updated changeset from patch to minor and added BREAKING note about constructor signature change."}

packages/sdk-core/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ ATPROTO_JWK_PRIVATE='{"keys":[{"kty":"EC","crv":"P-256",...}]}'
128128
> **Auto-generated loopback params**: When `clientId` is `http://localhost` (bare, no query params), the SDK
129129
> automatically appends `scope` and `redirect_uri` from your config. If you need custom query params, you can still
130130
> construct the URL manually (e.g.,
131-
> `http://localhost?scope=${encodeURIComponent(scope)}&redirect_uri=${encodeURIComponent(redirectUri)}`).
131+
> `http://localhost/?scope=${encodeURIComponent(scope)}&redirect_uri=${encodeURIComponent(redirectUri)}`).
132132
133133
> **Authorization Server Support**: The AT Protocol OAuth spec makes loopback support **optional**. Most AT Protocol
134134
> servers support loopback clients for development, but verify your target authorization server supports this feature.

0 commit comments

Comments
 (0)