Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Platform apis #24

Open
wants to merge 26 commits into
base: master
Choose a base branch
from
Open

Platform apis #24

wants to merge 26 commits into from

Conversation

AnthonyRonning
Copy link
Contributor

@AnthonyRonning AnthonyRonning commented Feb 24, 2025

Summary by CodeRabbit

  • Documentation

    • Expanded developer documentation outlining comprehensive API usage for organization, project, and secret management, including configuration for email and OAuth settings and detailed code examples.
    • Added a complete example of using the Developer Platform API in the documentation.
    • Introduced a new docs/PLATFORM.md file detailing the Developer Platform API.
  • New Features

    • Introduced new developer authentication and management capabilities via a dedicated provider and hook, enabling streamlined operations such as login, registration, and session handling.
    • Added robust API interfaces for managing organizations, projects, secrets, and memberships, including methods for inviting developers and managing roles.
    • New command added for testing specific files to improve testing capabilities.
    • Introduced a new API configuration service to manage endpoints for application and platform APIs.
  • Tests

    • Enhanced integration tests to validate authentication, organization, project, and secret management workflows, ensuring consistent and reliable performance.
    • Introduced new tests specifically for developer-related authentication methods.
  • Chores

    • Updated version number in package.json and modified peer dependencies for broader compatibility with React versions.
    • Added a new entry to .gitignore for ignoring .pbmd files.
    • Added new environment variables for secure handling of sensitive information during testing in the GitHub Actions workflow.

Copy link

coderabbitai bot commented Feb 24, 2025

Walkthrough

This pull request introduces comprehensive documentation and implementation for the Developer Platform API. A new section is added to the README with details and examples covering authentication, organization, project, secret, email, OAuth, and membership management. Additionally, new React context components and hooks are provided to support these operations. A robust API interface is implemented in a new module, and multiple integration tests have been updated or added to validate the new functionality and updated import paths.

Changes

File(s) Summary of Changes
README.md Added a new command for testing a specific file using Bun, enhancing testing capabilities.
src/lib/developer.tsx, src/lib/developerContext.ts, src/lib/index.ts Introduced the OpenSecretDeveloper context provider, the useOpenSecretDeveloper hook, and new developer-related types and exports.
src/lib/platformApi.ts Added a comprehensive API interface with new types and functions for authentication, organization, project, secret, email, OAuth settings, and membership operations.
src/lib/test/... Updated import paths, added an API URL loader, and integrated new tests for authentication, organization, project, secret management, and developer hook functionalities in various integration test files.
package.json Updated version and peer/dev dependencies for React and React DOM.
src/lib/api.ts, src/lib/attestation.ts, src/lib/encryptedApi.ts, src/lib/getAttestation.ts, src/lib/util.ts, src/lib/context.ts Introduced optional parameters for API functions to specify custom API URLs and modified error handling logic.
vite.config.ts Updated Rollup configuration to externalize React and React DOM dependencies more comprehensively.
.gitignore Added a new entry to ignore .pbmd files.
docs/PLATFORM.md New documentation file introduced for the Developer Platform API, detailing its functionalities and usage.

Possibly related PRs

  • Third party developers #23: Modifications related to the OpenSecretDeveloper component and useOpenSecretDeveloper hook, affecting API interactions and parameter handling.
  • Fix local attestations #20: Changes in the verifyAttestation function, specifically in how the API URL is handled, with the main PR introducing an explicitApiUrl parameter while the retrieved PR removes the apiUrl parameter.

Poem

I’m a swift rabbit, code hopping in style,
Building contexts and hooks that compile.
API secrets and projects, all in one race,
With every new method, I brighten the space.
Bugs, beware—I nibble them down,
A coding bunny, reigning with renown! 🐇✨

✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (5)
src/lib/test/platform-api-url-loader.ts (1)

6-8: Enhance error message with setup instructions.

The error message could be more helpful by including setup instructions.

-  throw new Error("VITE_OPEN_SECRET_API_URL must be set in environment variables");
+  throw new Error(
+    "VITE_OPEN_SECRET_API_URL must be set in environment variables.\n" +
+    "Please create a .env.local file in the project root with:\n" +
+    "VITE_OPEN_SECRET_API_URL=<your-api-url>"
+  );
src/lib/developer.test.ts (1)

41-41: Remove or reference the unused loginError.
ESLint complains this variable is unused. Either handle it or remove it for cleaner code.

Apply this diff to remove it:

-} catch (loginError) {
+} catch (_) {
🧰 Tools
🪛 ESLint

[error] 41-41: 'loginError' is defined but never used.

(@typescript-eslint/no-unused-vars)

src/lib/developer.tsx (2)

313-314: Implement the platform user fetch endpoint or remove the placeholder comment.
This TODO comment indicates missing functionality. Completing it will provide the developer’s user info in fetchDeveloper().

Do you want me to propose a skeleton implementation for fetching the developer’s user data?


318-320: Refine error handling to maintain type safety.
Currently, the error is caught and logged without casting or checking its type. For better clarity and maintainability, consider narrowing the error type.

} catch (error) {
-  console.error("Failed to fetch developer:", error);
+  if (error instanceof Error) {
+    console.error("Failed to fetch developer:", error.message);
+  } else {
+    console.error("Failed to fetch developer:", error);
+  }
src/lib/platformApi.ts (1)

2-2: Remove the unused encode import.
ESLint notes that encode is imported but never used.

Apply this diff to remove it:

-import { encode } from "@stablelib/base64";
🧰 Tools
🪛 ESLint

[error] 2-2: 'encode' is defined but never used.

(@typescript-eslint/no-unused-vars)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ca1feb4 and 1a29eba.

📒 Files selected for processing (7)
  • README.md (1 hunks)
  • src/lib/developer.test.ts (1 hunks)
  • src/lib/developer.tsx (1 hunks)
  • src/lib/developerContext.ts (1 hunks)
  • src/lib/index.ts (1 hunks)
  • src/lib/platformApi.ts (1 hunks)
  • src/lib/test/platform-api-url-loader.ts (1 hunks)
🧰 Additional context used
🪛 LanguageTool
README.md

[uncategorized] ~197-~197: A comma may be missing after the conjunctive/linking adverb ‘Currently’.
Context: ...oper.test.ts --env-file .env.local ``` Currently this build step requires npx because ...

(SENT_START_CONJUNCTIVE_LINKING_ADVERB_COMMA)

🪛 GitHub Check: test
src/lib/developer.test.ts

[failure] 12-12: error: Test developer credentials must be set in .env.local

  at /home/runner/work/OpenSecret-SDK/OpenSecret-SDK/src/lib/developer.test.ts:12:9
🪛 ESLint
src/lib/developer.test.ts

[error] 41-41: 'loginError' is defined but never used.

(@typescript-eslint/no-unused-vars)


[error] 59-59: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 100-100: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 110-110: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 122-122: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 143-143: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 154-154: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 163-163: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 172-172: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 211-211: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 228-228: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 237-237: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 240-240: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 257-257: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 262-262: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 293-293: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 300-300: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 340-340: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 368-368: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 383-383: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 391-391: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 399-399: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 402-402: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 425-425: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 429-429: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 472-472: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 516-516: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 521-521: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 542-542: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 548-548: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 637-637: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 659-659: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 668-668: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 676-676: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 683-683: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 711-711: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 721-721: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 729-729: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 739-739: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 761-761: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 769-769: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 782-782: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 789-789: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 820-820: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 828-828: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 881-881: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 906-906: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 914-914: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 924-924: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 932-932: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 943-943: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 980-980: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 991-991: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1049-1049: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1056-1056: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1081-1081: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1091-1091: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1175-1175: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1207-1207: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1220-1220: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1234-1234: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1247-1247: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1260-1260: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1271-1271: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1319-1319: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1342-1342: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1420-1420: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1436-1436: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1480-1480: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1499-1499: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1534-1534: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1547-1547: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1559-1559: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1575-1575: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1666-1666: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1706-1706: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)

src/lib/platformApi.ts

[error] 2-2: 'encode' is defined but never used.

(@typescript-eslint/no-unused-vars)

🪛 GitHub Actions: Library Tests
src/lib/developer.test.ts

[error] 1-1: Unhandled error between tests

🔇 Additional comments (5)
src/lib/developerContext.ts (1)

1-10: Well-implemented custom hook!

The implementation follows React's best practices:

  • Proper naming convention for custom hooks
  • Appropriate error handling for context usage
  • Consistent with the pattern used by other context hooks
README.md (1)

192-196: LGTM!

Clear and helpful instructions for running specific tests, with a practical example.

src/lib/index.ts (1)

12-27: LGTM!

Well-organized exports that maintain consistency with the existing pattern:

  • Provider and context exports grouped together
  • Hook exports under a common section
  • Types grouped by functionality
src/lib/developer.test.ts (1)

11-13: Ensure proper environment variable setup to avoid pipeline failures.
The pipeline log indicates a failure due to missing credentials. Make sure .env.local (or equivalent) provides valid values for VITE_TEST_DEVELOPER_EMAIL, VITE_TEST_DEVELOPER_PASSWORD, and VITE_TEST_DEVELOPER_NAME.

Would you like me to generate a script that checks for these environment variables globally or attempt a web search for up-to-date environment variable handling best practices?

🧰 Tools
🪛 GitHub Check: test

[failure] 12-12: error: Test developer credentials must be set in .env.local

  at /home/runner/work/OpenSecret-SDK/OpenSecret-SDK/src/lib/developer.test.ts:12:9
src/lib/developer.tsx (1)

357-361: Provider usage looks clean.
The context value is well-defined and covers all developer operations. The approach is consistent with React context best practices.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (2)
src/lib/developer.tsx (1)

285-290: Complete the developer fetching logic.

A TODO comment indicates that the user fetch endpoint is not yet implemented. Without it, some developer-based features may be unavailable or incomplete. Consider implementing and testing this soon.

src/lib/platformApi.ts (1)

2-2: Remove unused import or integrate it.

The encode import is never used. Either remove it to satisfy ESLint or reference it where necessary.

- import { encode } from "@stablelib/base64";
🧰 Tools
🪛 ESLint

[error] 2-2: 'encode' is defined but never used.

(@typescript-eslint/no-unused-vars)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1a29eba and 4758dde.

📒 Files selected for processing (3)
  • src/lib/developer.test.ts (1 hunks)
  • src/lib/developer.tsx (1 hunks)
  • src/lib/platformApi.ts (1 hunks)
🧰 Additional context used
🪛 ESLint
src/lib/platformApi.ts

[error] 2-2: 'encode' is defined but never used.

(@typescript-eslint/no-unused-vars)

src/lib/developer.test.ts

[error] 41-41: 'loginError' is defined but never used.

(@typescript-eslint/no-unused-vars)


[error] 59-59: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 100-100: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 110-110: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 122-122: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 143-143: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 154-154: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 163-163: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 172-172: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 211-211: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 228-228: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 237-237: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 240-240: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 257-257: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 262-262: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 293-293: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 300-300: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 340-340: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 368-368: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 383-383: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 391-391: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 399-399: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 402-402: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 425-425: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 429-429: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 472-472: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 516-516: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 521-521: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 542-542: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 548-548: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 637-637: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 659-659: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 668-668: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 676-676: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 683-683: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 711-711: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 721-721: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 729-729: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 739-739: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 761-761: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 769-769: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 782-782: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 789-789: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 820-820: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 828-828: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 881-881: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 906-906: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 914-914: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 924-924: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 932-932: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 943-943: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 976-976: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 987-987: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1045-1045: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1054-1054: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1079-1079: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1089-1089: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1173-1173: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1205-1205: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1218-1218: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1232-1232: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1245-1245: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1258-1258: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1269-1269: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1317-1317: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1340-1340: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1418-1418: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1434-1434: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1478-1478: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1497-1497: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1532-1532: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1545-1545: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1557-1557: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1573-1573: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1664-1664: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1704-1704: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1766-1766: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1834-1834: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1858-1858: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1874-1874: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1996-1996: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 2034-2034: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 2058-2058: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 2083-2083: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 2111-2111: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 2127-2127: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)

🪛 GitHub Check: test
src/lib/developer.test.ts

[failure] 12-12: error: Test developer credentials must be set in .env.local

  at /home/runner/work/OpenSecret-SDK/OpenSecret-SDK/src/lib/developer.test.ts:12:9
🪛 GitHub Actions: Library Tests
src/lib/developer.test.ts

[error] 1-1: Unhandled error between tests

🔇 Additional comments (3)
src/lib/developer.test.ts (3)

1-1: Investigate potential unhandled test failures.

The pipeline reports an “Unhandled error between tests.” Consider wrapping your test logic and async calls in try/catch blocks or using proper test lifecycle hooks (e.g., afterEach) to safely handle any errors that occur outside of individual test scopes.

🧰 Tools
🪛 GitHub Actions: Library Tests

[error] 1-1: Unhandled error between tests


11-13: Avoid hard failure when environment variables are missing.

Currently, the test suite throws an error if developer credentials are not set, causing pipeline failures without recourse. Consider gracefully skipping or marking the test as pending if credentials are absent.

🧰 Tools
🪛 GitHub Check: test

[failure] 12-12: error: Test developer credentials must be set in .env.local

  at /home/runner/work/OpenSecret-SDK/OpenSecret-SDK/src/lib/developer.test.ts:12:9

41-41: Consider replacing any with stricter types.

ESLint flags the use of any in multiple catch blocks. For better type safety, use unknown and then narrow the type, or define a custom error type.

Also applies to: 59-59, 100-100, 110-110, 122-122, 143-143, 154-154, 163-163, 172-172, 211-211, 228-228, 237-237, 240-240, 257-257, 262-262, 293-293, 300-300, 340-340, 368-368, 383-383, 391-391, 399-399, 402-402, 425-425, 429-429, 472-472, 516-516, 521-521, 542-542, 548-548, 637-637, 659-659, 668-668, 676-676, 683-683, 711-711, 721-721, 729-729, 739-739, 761-761, 769-769, 782-782, 789-789, 820-820, 828-828, 881-881, 906-906, 914-914, 924-924, 932-932, 943-943, 976-976, 987-987, 1045-1045, 1054-1054, 1079-1079, 1089-1089, 1173-1173, 1205-1205, 1218-1218, 1232-1232, 1245-1245, 1258-1258, 1269-1269, 1317-1317, 1340-1340, 1418-1418, 1434-1434, 1478-1478, 1497-1497, 1532-1532, 1545-1545, 1557-1557, 1573-1573, 1664-1664, 1704-1704, 1766-1766, 1834-1834, 1858-1858, 1874-1874, 1996-1996, 2034-2034, 2058-2058, 2083-2083, 2111-2111, 2127-2127

🧰 Tools
🪛 ESLint

[error] 41-41: 'loginError' is defined but never used.

(@typescript-eslint/no-unused-vars)

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (3)
src/lib/developer.tsx (2)

264-270: Consider providing a fallback or soft error handling if apiUrl is missing.
Currently, the component throws an error when apiUrl is empty. This can break the entire app if the parent component does not catch it. If you want a more graceful fallback, consider conditionally rendering an error UI or logging a warning instead of throwing an error.


285-290: Implement the fetchDeveloper endpoint or remove the TODO.
A TODO comment signals that the developer loading logic is incomplete. The function sets the developer to undefined and logs an error but doesn’t make an actual API request. Confirm whether you plan to implement the user fetch soon or if you want to remove it.

src/lib/platformApi.ts (1)

2-2: Remove unused import or utilize it.
The function encode from @stablelib/base64 is imported on line 2 but never used. Consider removing the import to satisfy lint checks and avoid confusion.

- import { encryptedApiCall, authenticatedApiCall } from "./encryptedApi";
- import { encode } from "@stablelib/base64";
+ import { encryptedApiCall, authenticatedApiCall } from "./encryptedApi";
🧰 Tools
🪛 ESLint

[error] 2-2: 'encode' is defined but never used.

(@typescript-eslint/no-unused-vars)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4758dde and 8bf3bee.

📒 Files selected for processing (2)
  • src/lib/developer.tsx (1 hunks)
  • src/lib/platformApi.ts (1 hunks)
🧰 Additional context used
🪛 ESLint
src/lib/platformApi.ts

[error] 2-2: 'encode' is defined but never used.

(@typescript-eslint/no-unused-vars)

🔇 Additional comments (3)
src/lib/developer.tsx (2)

273-283: Heads-up on potential SSR issues when accessing window.localStorage.
If you ever run this code in a server-side rendering environment, calls to window will fail. You might consider checking for the browser environment before calling window.localStorage.


303-332: Context initialization and usage look solid.
The default context value and the provided methods align well with the platformApi utilities. Nicely done!

src/lib/platformApi.ts (1)

1-315: Overall API structure is well-organized.
The typed API calls match expected endpoints, and the use of async/await for each function is consistent and readable. Good job!

🧰 Tools
🪛 ESLint

[error] 2-2: 'encode' is defined but never used.

(@typescript-eslint/no-unused-vars)

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (6)
src/lib/test/integration/developerHook.test.ts (2)

17-46: Consider verifying post-signIn local states in addition to the mocked response

Currently, the test only verifies the mock function call. For completeness, consider checking that the developer's state or any relevant localStorage entries are updated afterward if your hook or context modifies them.


82-146: Add negative test case for signUp

A negative test could confirm that passing invalid arguments (e.g., missing email) indeed triggers a failure for signUp. This helps ensure comprehensive test coverage.

src/lib/developer.tsx (2)

294-301: Good practice enforcing a non-empty API URL

Throwing an error if apiUrl is empty helps avoid misconfiguration. Consider also logging additional context or offering fallback endpoints if appropriate for your environment.


323-329: Enhance error handling for fetching developer

Currently, errors are only logged. Consider adding user-facing feedback or typed error handling to improve developer experience and reduce silent failures.

README.md (1)

567-567: Add a comma after "Currently" to improve readability.

A small grammar fix will help clarify the sentence.

- Currently this build step requires `npx` because of [a Bun incompatibility...]
+ Currently, this build step requires `npx` because of [a Bun incompatibility...]
🧰 Tools
🪛 LanguageTool

[uncategorized] ~567-~567: A comma may be missing after the conjunctive/linking adverb ‘Currently’.
Context: ...oper.test.ts --env-file .env.local ``` Currently this build step requires npx because ...

(SENT_START_CONJUNCTIVE_LINKING_ADVERB_COMMA)

src/lib/platformApi.ts (1)

2-2: Remove unused import.

This import is not used anywhere, and removing it resolves the ESLint warning.

 import { encryptedApiCall, authenticatedApiCall } from "./encryptedApi";
-import { encode } from "@stablelib/base64";
🧰 Tools
🪛 ESLint

[error] 2-2: 'encode' is defined but never used.

(@typescript-eslint/no-unused-vars)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8bf3bee and 99338e1.

📒 Files selected for processing (9)
  • README.md (2 hunks)
  • src/lib/developer.tsx (1 hunks)
  • src/lib/platformApi.ts (1 hunks)
  • src/lib/test/integration/ai.test.ts (1 hunks)
  • src/lib/test/integration/api.test.ts (1 hunks)
  • src/lib/test/integration/attestation.test.ts (1 hunks)
  • src/lib/test/integration/developer.test.ts (1 hunks)
  • src/lib/test/integration/developerHook.test.ts (1 hunks)
  • src/lib/test/integration/signing.test.ts (1 hunks)
✅ Files skipped from review due to trivial changes (4)
  • src/lib/test/integration/attestation.test.ts
  • src/lib/test/integration/signing.test.ts
  • src/lib/test/integration/ai.test.ts
  • src/lib/test/integration/api.test.ts
🧰 Additional context used
🪛 GitHub Check: test
src/lib/test/integration/developer.test.ts

[failure] 12-12: error: Test developer credentials must be set in .env.local

  at /home/runner/work/OpenSecret-SDK/OpenSecret-SDK/src/lib/test/integration/developer.test.ts:12:9
🪛 ESLint
src/lib/test/integration/developer.test.ts

[error] 41-41: 'loginError' is defined but never used.

(@typescript-eslint/no-unused-vars)


[error] 59-59: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 100-100: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 143-143: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 147-147: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 157-157: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 169-169: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 190-190: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 201-201: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 210-210: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 219-219: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 258-258: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 275-275: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 284-284: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 287-287: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 304-304: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 309-309: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 340-340: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 347-347: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 387-387: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 415-415: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 430-430: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 438-438: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 446-446: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 449-449: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 472-472: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 476-476: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 519-519: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 563-563: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 568-568: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 589-589: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 595-595: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 684-684: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 706-706: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 715-715: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 723-723: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 730-730: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 758-758: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 768-768: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 776-776: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 786-786: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 808-808: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 816-816: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 829-829: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 836-836: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 867-867: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 875-875: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 928-928: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 953-953: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 961-961: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 971-971: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 979-979: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 990-990: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1023-1023: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1034-1034: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1092-1092: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1101-1101: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1126-1126: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1136-1136: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1220-1220: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1252-1252: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1265-1265: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1279-1279: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1292-1292: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1305-1305: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1316-1316: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1364-1364: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1387-1387: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1465-1465: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1481-1481: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1525-1525: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1544-1544: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1579-1579: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1592-1592: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1604-1604: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1620-1620: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1711-1711: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1751-1751: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)

src/lib/platformApi.ts

[error] 2-2: 'encode' is defined but never used.

(@typescript-eslint/no-unused-vars)

🪛 LanguageTool
README.md

[uncategorized] ~274-~274: Loose punctuation mark.
Context: ...``` #### Developer State - developer: An object containing the current develo...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~284-~284: Loose punctuation mark.
Context: ...on(name: string): Promise`: Creates a new organization with the giv...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~285-~285: Loose punctuation mark.
Context: ...rganizations(): Promise<Organization[]>`: Lists all organizations the developer h...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~286-~286: Loose punctuation mark.
Context: ...anization(orgId: string): Promise`: Deletes an organization (requires owner...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~302-~302: Loose punctuation mark.
Context: ...description?: string): Promise`: Creates a new project within an organiz...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~303-~303: Loose punctuation mark.
Context: ...ects(orgId: string): Promise<Project[]>`: Lists all projects within an organizati...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~304-~304: Loose punctuation mark.
Context: ...g; status?: string }): Promise: Updates project details. - deleteProje...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~305-~305: Loose punctuation mark.
Context: ...ring, projectId: string): Promise`: Deletes a project. Example: ```tsx con...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~326-~326: Loose punctuation mark.
Context: ...secret: string): Promise`: Creates a new secret for a project. The...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~327-~327: Loose punctuation mark.
Context: ...ctId: string): Promise<ProjectSecret[]>: Lists all secrets for a project. - del...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~328-~328: Loose punctuation mark.
Context: ...string, keyName: string): Promise`: Deletes a project secret. Example: ```...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~355-~355: Loose punctuation mark.
Context: ...jectId: string): Promise`: Gets email configuration for a project....

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~356-~356: Loose punctuation mark.
Context: ... EmailSettings): Promise`: Updates email configuration. Example: ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~376-~376: Loose punctuation mark.
Context: ...jectId: string): Promise: Gets OAuth settings for a project. - u...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~377-~377: Loose punctuation mark.
Context: ... OAuthSettings): Promise`: Updates OAuth configuration. Example: ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~400-~400: Loose punctuation mark.
Context: ...le?: string): Promise<{ code: string }>`: Creates an invitation to join an organi...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~401-~401: Loose punctuation mark.
Context: ... string): Promise<OrganizationMember[]>`: Lists all members of an organization. -...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~402-~402: Loose punctuation mark.
Context: ...e: string): Promise: Updates a member's role. - removeMembe...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~403-~403: Loose punctuation mark.
Context: ... string, userId: string): Promise`: Removes a member from the organization....

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~404-~404: Loose punctuation mark.
Context: ...ceptInvite(code: string): Promise`: Accepts an organization invitation. Ex...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~567-~567: A comma may be missing after the conjunctive/linking adverb ‘Currently’.
Context: ...oper.test.ts --env-file .env.local ``` Currently this build step requires npx because ...

(SENT_START_CONJUNCTIVE_LINKING_ADVERB_COMMA)

🔇 Additional comments (4)
src/lib/test/integration/developerHook.test.ts (2)

1-15: Looks good overall

Clearing window.localStorage in beforeEach is a good approach, ensuring each test runs in a clean state. No immediate issues spotted here.


148-228: Good test coverage for signOut

Verifying token removal is critical. The approach of manually setting tokens before signOut is well done. The code looks maintainable and consistent.

src/lib/test/integration/developer.test.ts (1)

11-13: Ensure environment variables are set for test execution

The test will throw an error unless TEST_DEVELOPER_EMAIL, TEST_DEVELOPER_PASSWORD, and TEST_DEVELOPER_NAME are defined in .env.local. If these variables are unavailable in your CI environment, consider creating a fallback or skipping these tests automatically.

🧰 Tools
🪛 GitHub Check: test

[failure] 12-12: error: Test developer credentials must be set in .env.local

  at /home/runner/work/OpenSecret-SDK/OpenSecret-SDK/src/lib/test/integration/developer.test.ts:12:9
README.md (1)

169-566: Looks great and comprehensive!

Your documentation for the Developer Platform API is thorough and clear. The usage examples and explanations across authentication, organization, project, and secret management are well-explained.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~274-~274: Loose punctuation mark.
Context: ...``` #### Developer State - developer: An object containing the current develo...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~284-~284: Loose punctuation mark.
Context: ...on(name: string): Promise`: Creates a new organization with the giv...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~285-~285: Loose punctuation mark.
Context: ...rganizations(): Promise<Organization[]>`: Lists all organizations the developer h...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~286-~286: Loose punctuation mark.
Context: ...anization(orgId: string): Promise`: Deletes an organization (requires owner...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~302-~302: Loose punctuation mark.
Context: ...description?: string): Promise`: Creates a new project within an organiz...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~303-~303: Loose punctuation mark.
Context: ...ects(orgId: string): Promise<Project[]>`: Lists all projects within an organizati...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~304-~304: Loose punctuation mark.
Context: ...g; status?: string }): Promise: Updates project details. - deleteProje...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~305-~305: Loose punctuation mark.
Context: ...ring, projectId: string): Promise`: Deletes a project. Example: ```tsx con...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~326-~326: Loose punctuation mark.
Context: ...secret: string): Promise`: Creates a new secret for a project. The...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~327-~327: Loose punctuation mark.
Context: ...ctId: string): Promise<ProjectSecret[]>: Lists all secrets for a project. - del...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~328-~328: Loose punctuation mark.
Context: ...string, keyName: string): Promise`: Deletes a project secret. Example: ```...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~355-~355: Loose punctuation mark.
Context: ...jectId: string): Promise`: Gets email configuration for a project....

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~356-~356: Loose punctuation mark.
Context: ... EmailSettings): Promise`: Updates email configuration. Example: ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~376-~376: Loose punctuation mark.
Context: ...jectId: string): Promise: Gets OAuth settings for a project. - u...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~377-~377: Loose punctuation mark.
Context: ... OAuthSettings): Promise`: Updates OAuth configuration. Example: ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~400-~400: Loose punctuation mark.
Context: ...le?: string): Promise<{ code: string }>`: Creates an invitation to join an organi...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~401-~401: Loose punctuation mark.
Context: ... string): Promise<OrganizationMember[]>`: Lists all members of an organization. -...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~402-~402: Loose punctuation mark.
Context: ...e: string): Promise: Updates a member's role. - removeMembe...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~403-~403: Loose punctuation mark.
Context: ... string, userId: string): Promise`: Removes a member from the organization....

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~404-~404: Loose punctuation mark.
Context: ...ceptInvite(code: string): Promise`: Accepts an organization invitation. Ex...

(UNLIKELY_OPENING_PUNCTUATION)

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (9)
src/lib/util.ts (1)

11-14: Consider using AbortController with sleep function

The sleep function implementation is clean and straightforward. For more advanced use cases, consider enhancing it to support cancellation via AbortController to prevent memory leaks when used in components that unmount before the timeout completes.

-export function sleep(ms: number): Promise<void> {
-  return new Promise(resolve => setTimeout(resolve, ms));
+export function sleep(ms: number, signal?: AbortSignal): Promise<void> {
+  return new Promise((resolve, reject) => {
+    if (signal?.aborted) {
+      return reject(new Error('Aborted'));
+    }
+    
+    const timeout = setTimeout(resolve, ms);
+    
+    signal?.addEventListener('abort', () => {
+      clearTimeout(timeout);
+      reject(new Error('Aborted'));
+    }, { once: true });
+  });
}
src/lib/encryptedApi.ts (1)

76-83: Enhanced API URL flexibility for platform calls

The implementation correctly determines if this is a platform API call and retrieves the appropriate URL from the global window object. This change adds flexibility by allowing different API endpoints for platform-specific operations.

However, there's no type declaration for window.__PLATFORM_API_URL__. Consider adding:

+// Add to a global.d.ts file or similar
+interface Window {
+  __PLATFORM_API_URL__?: string;
+}
src/lib/developer.tsx (4)

314-326: Consider server-side rendering compatibility.

Accessing window for storing the __PLATFORM_API_URL__ may lead to issues in server-side rendering (SSR) environments, where window is undefined. You might introduce checks or conditionally run this logic to avoid SSR breakages.


328-359: Potential repeated fetching logic.

fetchDeveloper() is called unconditionally on mount and also after sign-in or sign-up. Consider debouncing or ensuring multiple calls won't cause concurrency issues or extraneous network requests.


374-385: Maintain consistent error handling approach.

The signUp method logs and re-throws errors, similar to signIn. Ensure all developer-facing error messages are uniform (both in content and format) to provide a consistent developer experience.


391-406: Refine sign-out error handling path.

During signOut, an error is logged but not surfaced to the UI or re-thrown. For a better user experience, consider displaying a notification or a specialized fallback if logout fails.

README.md (1)

193-267: Clarify potential security implications of localStorage usage.

While your instructions note that the auth tokens are stored in localStorage, it might be worth adding a sentence in the docs about potential XSS risks or alternative secure storage strategies.

src/lib/platformApi.ts (2)

103-116: Validate error strings in platformLogin.

The fallback message is "Failed to login". Confirm that you also parse any server error messages to provide diagnostic details for the developer.


360-366: Consider clarifying the invite acceptance flow.

The acceptInvite API call is concise. Document any prerequisites (like needing an account or to be logged out) to avoid confusion in edge cases.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 99338e1 and 1dd3757.

⛔ Files ignored due to path filters (1)
  • bun.lockb is excluded by !**/bun.lockb
📒 Files selected for processing (12)
  • README.md (2 hunks)
  • package.json (3 hunks)
  • src/lib/api.ts (2 hunks)
  • src/lib/attestation.ts (1 hunks)
  • src/lib/context.ts (1 hunks)
  • src/lib/developer.tsx (1 hunks)
  • src/lib/developerContext.ts (1 hunks)
  • src/lib/encryptedApi.ts (1 hunks)
  • src/lib/getAttestation.ts (3 hunks)
  • src/lib/platformApi.ts (1 hunks)
  • src/lib/util.ts (1 hunks)
  • vite.config.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/lib/developerContext.ts
🧰 Additional context used
🪛 LanguageTool
README.md

[uncategorized] ~280-~280: Loose punctuation mark.
Context: ...``` #### Developer State - developer: An object containing the current develo...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~291-~291: Loose punctuation mark.
Context: ...string): Promise`: Signs in a developer with the provided ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~292-~292: Loose punctuation mark.
Context: ...string): Promise`: Registers a new developer account with ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~293-~293: Loose punctuation mark.
Context: ...ly updated. - signOut(): Promise<void>: Signs out the current developer by remo...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~297-~297: Loose punctuation mark.
Context: ...on(name: string): Promise`: Creates a new organization with the giv...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~298-~298: Loose punctuation mark.
Context: ...rganizations(): Promise<Organization[]>`: Lists all organizations the developer h...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~299-~299: Loose punctuation mark.
Context: ...anization(orgId: string): Promise`: Deletes an organization (requires owner...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~315-~315: Loose punctuation mark.
Context: ...description?: string): Promise`: Creates a new project within an organiz...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~316-~316: Loose punctuation mark.
Context: ...ects(orgId: string): Promise<Project[]>`: Lists all projects within an organizati...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~317-~317: Loose punctuation mark.
Context: ...g; status?: string }): Promise: Updates project details. - deleteProje...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~318-~318: Loose punctuation mark.
Context: ...ring, projectId: string): Promise`: Deletes a project. Example: ```tsx con...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~339-~339: Loose punctuation mark.
Context: ...secret: string): Promise`: Creates a new secret for a project. The...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~340-~340: Loose punctuation mark.
Context: ...ctId: string): Promise<ProjectSecret[]>: Lists all secrets for a project. - del...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~341-~341: Loose punctuation mark.
Context: ...string, keyName: string): Promise`: Deletes a project secret. Example: ```...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~368-~368: Loose punctuation mark.
Context: ...jectId: string): Promise`: Gets email configuration for a project....

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~369-~369: Loose punctuation mark.
Context: ... EmailSettings): Promise`: Updates email configuration. Example: ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~389-~389: Loose punctuation mark.
Context: ...jectId: string): Promise: Gets OAuth settings for a project. - u...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~390-~390: Loose punctuation mark.
Context: ... OAuthSettings): Promise`: Updates OAuth configuration. Example: ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~413-~413: Loose punctuation mark.
Context: ...le?: string): Promise<{ code: string }>`: Creates an invitation to join an organi...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~414-~414: Loose punctuation mark.
Context: ... string): Promise<OrganizationMember[]>`: Lists all members of an organization. -...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~415-~415: Loose punctuation mark.
Context: ...e: string): Promise: Updates a member's role. - removeMembe...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~416-~416: Loose punctuation mark.
Context: ... string, userId: string): Promise`: Removes a member from the organization....

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~417-~417: Loose punctuation mark.
Context: ...ceptInvite(code: string): Promise`: Accepts an organization invitation. Ex...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~580-~580: A comma may be missing after the conjunctive/linking adverb ‘Currently’.
Context: ...oper.test.ts --env-file .env.local ``` Currently this build step requires npx because ...

(SENT_START_CONJUNCTIVE_LINKING_ADVERB_COMMA)

🔇 Additional comments (20)
vite.config.ts (1)

54-61: Good improvement to external dependencies configuration

The updated configuration properly externalizes React and React DOM along with their internal modules, which is important for compatibility with both React 18 and 19. The regex patterns will ensure any submodules are correctly excluded from the bundle.

src/lib/util.ts (2)

3-9: Simplified useOnMount implementation is more robust

The updated implementation correctly uses an empty dependency array to ensure the callback runs only once on mount. Removing the hasRun reference makes the code cleaner and less prone to errors.


16-21: Good practice for extending Window interface

Properly extending the Window interface to type the custom property is a good TypeScript practice. This will ensure type safety when accessing window.__PLATFORM_API_URL__ throughout the codebase.

src/lib/getAttestation.ts (3)

29-30: Rename parameter for clarity and consistency

Good change renaming apiUrl to explicitApiUrl, which makes the parameter's purpose clearer and aligns with other functions in the codebase.


51-51:

❓ Verification inconclusive

Ensure parameter propagation is complete

The explicitApiUrl parameter is now correctly passed to verifyAttestation. Make sure this parameter is properly handled in the implementation of verifyAttestation as well.


🏁 Script executed:

#!/bin/bash
# Check how verifyAttestation handles the explicitApiUrl parameter
ast-grep --pattern 'export function verifyAttestation($_,$_) {
  $$$
}'

Length of output: 73


Action Required: Verify explicitApiUrl Handling in verifyAttestation

The propagation of the explicitApiUrl parameter from getAttestation.ts appears correct. However, our initial verification command for the implementation of verifyAttestation did not yield any output. Please re-check manually (or with additional scripts) that the implementation of verifyAttestation actually makes use of the explicitApiUrl parameter.

  • File/Location to Verify:
    • Check the definition of verifyAttestation (likely in the same or a related module) for proper usage of explicitApiUrl.

To further validate, please consider running the following additional script:

Once confirmed, you may then safely conclude that parameter propagation is complete.


🏁 Script executed:

[run_scripts]
#!/bin/bash
# Display the implementation of verifyAttestation with extra context to confirm explicitApiUrl usage.
rg -n "export function verifyAttestation" -A 30

Length of output: 171


Confirm explicitApiUrl usage in verifyAttestation

The explicitApiUrl parameter is correctly passed from getAttestation.ts. However, our automated search did not reveal clear evidence on how it’s handled inside the verifyAttestation implementation. Please verify manually (or with additional targeted scripts) that verifyAttestation correctly utilizes explicitApiUrl.


59-63:

❓ Verification inconclusive

Consistent parameter propagation

The explicitApiUrl parameter is now correctly passed to keyExchange. Ensure all other related functions in the codebase have been updated consistently to handle this parameter.


🏁 Script executed:

#!/bin/bash
# Check how keyExchange handles the explicitApiUrl parameter
ast-grep --pattern 'export function keyExchange($_,$_,$_) {
  $$$
}'

Length of output: 70


Below is a new verification script to hunt down the definition(s) and usages of keyExchange across the repository. This should help ensure that the explicitApiUrl parameter is consistently propagated:

Once this script is executed, please verify that:

  • The keyExchange function (or functions) is defined using a signature that includes the explicitApiUrl parameter.
  • All calls to keyExchange throughout the codebase consistently pass this new parameter.

From the review snippet in src/lib/getAttestation.ts (lines 59–63), it’s clear that explicitApiUrl is passed correctly to keyExchange. However, the initial AST grep did not return a match for the function definition—possibly due to naming variations or alternate syntaxes. Manual inspection of the search results is recommended.

Next Steps:

  • Confirm that your updated implementation of keyExchange (or its wrappers) properly accepts and uses explicitApiUrl.
  • Check that any other functions dependent on keyExchange are updated accordingly.

Explicit Parameter Propagation Verification:

  • File: src/lib/getAttestation.ts
  • Snippet:
        const { encrypted_session_key, session_id } = await keyExchange(
          encode(clientKeyPair.publicKey),
          attestationNonce,
          explicitApiUrl
        );
  • Action Required: Manually review the output of the search to ensure that the keyExchange definition incorporates explicitApiUrl consistently across the codebase.

Please address these points to ensure cross-cutting consistency in parameter propagation.


🏁 Script executed:

[run_scripts]
#!/bin/bash
# Search for any definition or usage of keyExchange in the repository and review nearby context for explicitApiUrl
rg -n "keyExchange\\s*\\(" .

Length of output: 308


Ensure Consistent Parameter Propagation Across the Codebase

  • The invocation in src/lib/getAttestation.ts (lines 59–63) now correctly passes explicitApiUrl to keyExchange:
        const { encrypted_session_key, session_id } = await keyExchange(
          encode(clientKeyPair.publicKey),
          attestationNonce,
          explicitApiUrl
        );
  • A repository-wide search shows that the keyExchange function is defined in src/lib/api.ts (line 218). However, the previous AST grep did not yield details on its signature. Please verify that the function definition in src/lib/api.ts accepts and correctly uses the explicitApiUrl parameter.
  • Also, check that any other functions that depend on or propagate parameters from keyExchange are updated accordingly.

Please manually inspect src/lib/api.ts to confirm that the parameter is consistently handled across the codebase.

src/lib/encryptedApi.ts (1)

87-87: Consistent use of explicitApiUrl parameter

Good implementation of the attestation renewal logic using the same explicitApiUrl parameter.

src/lib/attestation.ts (2)

260-260: Added flexibility with optional explicitApiUrl parameter

The function signature has been properly updated to accept an optional API URL parameter, making the attestation verification more flexible.


262-267: Correct implementation of API URL fallback

The implementation correctly uses the explicitApiUrl parameter when provided and falls back to the default getApiUrl() when not specified. This ensures backward compatibility while adding new functionality.

package.json (3)

3-3: Version bump appropriately reflects new functionality

The minor version increment from 0.4.0 to 0.4.1 is appropriate for backwards-compatible functionality improvements.


27-28: React peer dependency compatibility broadened

Good practice to broaden React compatibility to include both v18 and v19, which makes the library more flexible for consumers using different React versions.


44-45: Updated React type definitions

Type definitions have been correctly updated to match the broadened React compatibility range.

src/lib/api.ts (2)

208-210: Added flexibility to fetchAttestationDocument

The function now correctly accepts an optional explicitApiUrl parameter and falls back to the default apiUrl when not provided.


219-224: Added explicitApiUrl support to keyExchange

The keyExchange function has been enhanced with an explicitApiUrl parameter and properly implements the fallback mechanism, maintaining consistent behavior across related functions.

src/lib/developer.tsx (1)

361-372: Evaluate localStorage security risks.

Storing access and refresh tokens in localStorage can expose them to XSS attacks. Confirm that this trade-off is acceptable in your threat model, or consider more secure storage methods (e.g., HTTP-only cookies).

README.md (2)

171-189: Documentation thoroughly addresses the new Developer Platform API.

The new section clearly explains usage of OpenSecretDeveloper, covering authentication, organization, project, secrets, and membership management. No major concerns here.


575-579: Great addition of a targeted test command.

Highlighting --test-name-pattern usage is beneficial for developers to quickly isolate relevant test cases, especially for new Developer Platform APIs.

src/lib/platformApi.ts (3)

95-101: Confirm expected behavior when platformApiUrl is not set.

getPlatformApiUrl() returns an empty string if setPlatformApiUrl was never called. Consider throwing an error or providing a fallback to avoid unintentionally calling APIs against an empty or undefined host.


144-166: Refresh tokens in localStorage.

Similar to other methods, storing the tokens in localStorage poses security considerations. Validate that your threat model allows for this risk, or consider more secure session handling.


320-323: Helpful email validation check.

Throwing an error for empty email is a solid early catch. Ensure consistent validation patterns (like checking for valid email format) if needed.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (7)
src/lib/developer.tsx (5)

38-39: Consider a separate interface for the developer object
Carrying around the developer fields in an optional property might hamper code clarity. A dedicated interface for the developer data could improve readability and maintainability.


392-409: Potential safer storage than localStorage
Storing sensitive tokens in localStorage can expose them to XSS attacks. Consider secure HttpOnly cookies or another protected storage mechanism if the security model allows.


440-455: Nonce usage in getAttestationDocument
Using a nonce for attestation validation is a good security measure. For full protection, consider additional replay defense mechanisms, if recommended by your attestation spec.


456-479: SignIn and SignUp flows
Handling errors with console logs is a decent start. In production, consider more user-friendly notifications or typed error responses to improve user experience.


486-534: SignOut error handling
If the logout API fails, the code proceeds to remove tokens anyway. This may be fine, but consider surfacing an explicit error or retrying to ensure graceful handling of server-side failures.

README.md (1)

595-595: Add a comma after "Currently"
A small grammatical improvement can be made around line 595.

-Currently this build step requires `npx` because...
+Currently, this build step requires `npx` because...
🧰 Tools
🪛 LanguageTool

[uncategorized] ~595-~595: A comma may be missing after the conjunctive/linking adverb ‘Currently’.
Context: ...oper.test.ts --env-file .env.local ``` Currently this build step requires npx because ...

(SENT_START_CONJUNCTIVE_LINKING_ADVERB_COMMA)

src/lib/platformApi.ts (1)

168-192: Organization creation & deletion
Creating, listing, and deleting organizations is straightforward. Ensure proper error handling for role-based restrictions or unauthorized requests.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1dd3757 and 046f849.

📒 Files selected for processing (4)
  • .gitignore (1 hunks)
  • README.md (2 hunks)
  • src/lib/developer.tsx (1 hunks)
  • src/lib/platformApi.ts (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • .gitignore
🧰 Additional context used
🪛 LanguageTool
README.md

[uncategorized] ~281-~281: Loose punctuation mark.
Context: ...``` #### Developer State - developer: An object containing the current develo...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~292-~292: Loose punctuation mark.
Context: ...string): Promise`: Signs in a developer with the provided ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~293-~293: Loose punctuation mark.
Context: ...string): Promise`: Registers a new developer account with ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~294-~294: Loose punctuation mark.
Context: ...ly updated. - signOut(): Promise<void>: Signs out the current developer by remo...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~295-~295: Loose punctuation mark.
Context: ...l. - refetchDeveloper(): Promise<void>: Refreshes the developer's authenticatio...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~299-~299: Loose punctuation mark.
Context: ... Attestation Verification - pcrConfig: An object containing additional PCR0 ha...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~300-~300: Loose punctuation mark.
Context: ... to validate against. - getAttestation: Gets attestation from the enclave. - `a...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~301-~301: Loose punctuation mark.
Context: ...ation from the enclave. - authenticate: Authenticates an attestation document. ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~302-~302: Loose punctuation mark.
Context: ...on document. - parseAttestationForView: Parses an attestation document for view...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~303-~303: Loose punctuation mark.
Context: ...document for viewing. - awsRootCertDer: AWS root certificate in DER format. - `...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~304-~304: Loose punctuation mark.
Context: ... in DER format. - expectedRootCertHash: Expected hash of the AWS root certifica...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~305-~305: Loose punctuation mark.
Context: ...ertificate. - getAttestationDocument(): Gets and verifies an attestation docume...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~312-~312: Loose punctuation mark.
Context: ...on(name: string): Promise`: Creates a new organization with the giv...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~313-~313: Loose punctuation mark.
Context: ...rganizations(): Promise<Organization[]>`: Lists all organizations the developer h...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~314-~314: Loose punctuation mark.
Context: ...anization(orgId: string): Promise`: Deletes an organization (requires owner...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~330-~330: Loose punctuation mark.
Context: ...description?: string): Promise`: Creates a new project within an organiz...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~331-~331: Loose punctuation mark.
Context: ...ects(orgId: string): Promise<Project[]>`: Lists all projects within an organizati...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~332-~332: Loose punctuation mark.
Context: ...g; status?: string }): Promise: Updates project details. - deleteProje...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~333-~333: Loose punctuation mark.
Context: ...ring, projectId: string): Promise`: Deletes a project. Example: ```tsx con...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~354-~354: Loose punctuation mark.
Context: ...secret: string): Promise`: Creates a new secret for a project. The...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~355-~355: Loose punctuation mark.
Context: ...ctId: string): Promise<ProjectSecret[]>: Lists all secrets for a project. - del...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~356-~356: Loose punctuation mark.
Context: ...string, keyName: string): Promise`: Deletes a project secret. Example: ```...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~383-~383: Loose punctuation mark.
Context: ...jectId: string): Promise`: Gets email configuration for a project....

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~384-~384: Loose punctuation mark.
Context: ... EmailSettings): Promise`: Updates email configuration. Example: ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~404-~404: Loose punctuation mark.
Context: ...jectId: string): Promise: Gets OAuth settings for a project. - u...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~405-~405: Loose punctuation mark.
Context: ... OAuthSettings): Promise`: Updates OAuth configuration. Example: ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~428-~428: Loose punctuation mark.
Context: ...le?: string): Promise<{ code: string }>`: Creates an invitation to join an organi...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~429-~429: Loose punctuation mark.
Context: ... string): Promise<OrganizationMember[]>`: Lists all members of an organization. -...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~430-~430: Loose punctuation mark.
Context: ...e: string): Promise: Updates a member's role. - removeMembe...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~431-~431: Loose punctuation mark.
Context: ... string, userId: string): Promise`: Removes a member from the organization....

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~432-~432: Loose punctuation mark.
Context: ...ceptInvite(code: string): Promise`: Accepts an organization invitation. Ex...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~595-~595: A comma may be missing after the conjunctive/linking adverb ‘Currently’.
Context: ...oper.test.ts --env-file .env.local ``` Currently this build step requires npx because ...

(SENT_START_CONJUNCTIVE_LINKING_ADVERB_COMMA)

🔇 Additional comments (18)
src/lib/developer.tsx (9)

1-25: Imports look consistent and correct
All imports appear relevant and properly organized. No issues found.


26-36: Clear type definitions
The typed roles and organization/project details are well-defined and consistent with the rest of the codebase.


41-86: Well-documented API for signIn, signUp, and signOut
The thorough JSDoc comments clearly explain usage, parameters, and error handling. This is beneficial for developers integrating these functions.


87-145: Robust attestation logic
Attestation and authentication flows are thoughtfully documented, ensuring clarity for users needing secure enclave-based attestations.


146-316: Comprehensive coverage of platform operations
Creating, listing, updating, and deleting organizations, projects, secrets, and memberships is well-structured with descriptive JSDoc. The approach is straightforward and consistent.


318-364: Helpful default context
Providing default methods that throw instructive errors ensures consumers configure the provider correctly. This pattern helps catch usage errors early.


366-391: Ensure SSR compatibility
This component references window directly (e.g., localStorage and window.__PLATFORM_API_URL__), which can break server-side rendering. Consider conditionally checking typeof window !== 'undefined' before usage or providing SSR fallbacks.


411-438: Error handling
The fetchDeveloper method logs errors but sets developer to undefined without surfacing more details. If partial failures are possible (e.g., intermittent network issues), consider prompting the user or retrying.


536-541: Provider usage
Wrapping children inside the context fosters modular, maintainable code. This setup is concise, with minimal overhead. Great job.

README.md (2)

1-168: Comprehensive introduction and usage guides
The README thoroughly explains installation, usage, and authentication flows. This is highly beneficial for new users integrating OpenSecret.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~79-~79: Loose punctuation mark.
Context: ...: string, name?: string): Promise`: Signs up a new user with the provided e...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~80-~80: Loose punctuation mark.
Context: ...tring, password: string): Promise`: Signs in a guest user with their ID and...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~81-~81: Loose punctuation mark.
Context: ...teCode: string): Promise`: Creates a new guest account with just a...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~82-~82: Loose punctuation mark.
Context: ...: string, name?: string): Promise`: Converts current guest account to a reg...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~83-~83: Loose punctuation mark.
Context: ...ated under. - signOut(): Promise<void>: Signs out the current user. #### Key-V...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~87-~87: Loose punctuation mark.
Context: ...string, value: string): Promise`: Stores the provided value with the prov...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~88-~88: Loose punctuation mark.
Context: ...d key. - list(): Promise<KVListItem[]>: Retrieves all key-value pairs stored by...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~89-~89: Loose punctuation mark.
Context: ...ser. - del(key: string): Promise<void>: Deletes the value associated with the p...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~93-~93: Loose punctuation mark.
Context: ...ng, newPassword: string): Promise: Changes the user's password. - generat...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~94-~94: Loose punctuation mark.
Context: ...ce: string): Promise<{ token: string }>`: Generates a JWT token for use with pre-...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~99-~99: Loose punctuation mark.
Context: ...ring): Promise<{ private_key: string }>`: Retrieves the private key bytes for a g...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~112-~112: Loose punctuation mark.
Context: ...h?: string): Promise`: Retrieves the user's public key for the...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~121-~121: Loose punctuation mark.
Context: ...h?: string): Promise`: Signs a message using the specified alg...

(UNLIKELY_OPENING_PUNCTUATION)

🪛 markdownlint-cli2 (0.17.2)

5-5: Bare URL used
null

(MD034, no-bare-urls)


94-94: Bare URL used
null

(MD034, no-bare-urls)


169-613: Developer Platform API documentation
Excellent step-by-step code examples, covering critical aspects of organizations, projects, secrets, and attestation. This empowers developers to quickly adopt these features.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~281-~281: Loose punctuation mark.
Context: ...``` #### Developer State - developer: An object containing the current develo...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~292-~292: Loose punctuation mark.
Context: ...string): Promise`: Signs in a developer with the provided ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~293-~293: Loose punctuation mark.
Context: ...string): Promise`: Registers a new developer account with ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~294-~294: Loose punctuation mark.
Context: ...ly updated. - signOut(): Promise<void>: Signs out the current developer by remo...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~295-~295: Loose punctuation mark.
Context: ...l. - refetchDeveloper(): Promise<void>: Refreshes the developer's authenticatio...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~299-~299: Loose punctuation mark.
Context: ... Attestation Verification - pcrConfig: An object containing additional PCR0 ha...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~300-~300: Loose punctuation mark.
Context: ... to validate against. - getAttestation: Gets attestation from the enclave. - `a...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~301-~301: Loose punctuation mark.
Context: ...ation from the enclave. - authenticate: Authenticates an attestation document. ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~302-~302: Loose punctuation mark.
Context: ...on document. - parseAttestationForView: Parses an attestation document for view...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~303-~303: Loose punctuation mark.
Context: ...document for viewing. - awsRootCertDer: AWS root certificate in DER format. - `...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~304-~304: Loose punctuation mark.
Context: ... in DER format. - expectedRootCertHash: Expected hash of the AWS root certifica...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~305-~305: Loose punctuation mark.
Context: ...ertificate. - getAttestationDocument(): Gets and verifies an attestation docume...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~312-~312: Loose punctuation mark.
Context: ...on(name: string): Promise`: Creates a new organization with the giv...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~313-~313: Loose punctuation mark.
Context: ...rganizations(): Promise<Organization[]>`: Lists all organizations the developer h...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~314-~314: Loose punctuation mark.
Context: ...anization(orgId: string): Promise`: Deletes an organization (requires owner...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~330-~330: Loose punctuation mark.
Context: ...description?: string): Promise`: Creates a new project within an organiz...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~331-~331: Loose punctuation mark.
Context: ...ects(orgId: string): Promise<Project[]>`: Lists all projects within an organizati...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~332-~332: Loose punctuation mark.
Context: ...g; status?: string }): Promise: Updates project details. - deleteProje...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~333-~333: Loose punctuation mark.
Context: ...ring, projectId: string): Promise`: Deletes a project. Example: ```tsx con...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~354-~354: Loose punctuation mark.
Context: ...secret: string): Promise`: Creates a new secret for a project. The...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~355-~355: Loose punctuation mark.
Context: ...ctId: string): Promise<ProjectSecret[]>: Lists all secrets for a project. - del...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~356-~356: Loose punctuation mark.
Context: ...string, keyName: string): Promise`: Deletes a project secret. Example: ```...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~383-~383: Loose punctuation mark.
Context: ...jectId: string): Promise`: Gets email configuration for a project....

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~384-~384: Loose punctuation mark.
Context: ... EmailSettings): Promise`: Updates email configuration. Example: ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~404-~404: Loose punctuation mark.
Context: ...jectId: string): Promise: Gets OAuth settings for a project. - u...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~405-~405: Loose punctuation mark.
Context: ... OAuthSettings): Promise`: Updates OAuth configuration. Example: ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~428-~428: Loose punctuation mark.
Context: ...le?: string): Promise<{ code: string }>`: Creates an invitation to join an organi...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~429-~429: Loose punctuation mark.
Context: ... string): Promise<OrganizationMember[]>`: Lists all members of an organization. -...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~430-~430: Loose punctuation mark.
Context: ...e: string): Promise: Updates a member's role. - removeMembe...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~431-~431: Loose punctuation mark.
Context: ... string, userId: string): Promise`: Removes a member from the organization....

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~432-~432: Loose punctuation mark.
Context: ...ceptInvite(code: string): Promise`: Accepts an organization invitation. Ex...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~595-~595: A comma may be missing after the conjunctive/linking adverb ‘Currently’.
Context: ...oper.test.ts --env-file .env.local ``` Currently this build step requires npx because ...

(SENT_START_CONJUNCTIVE_LINKING_ADVERB_COMMA)

src/lib/platformApi.ts (7)

1-25: Use of common API wrappers is consistent
The encryptedApiCall and authenticatedApiCall abstractions foster cleaner code and clarify responsibilities.


26-66: Clear user and org data structures
PlatformUser and PlatformOrg types capture essential properties, including timestamps and roles. This improves maintainability.


103-116: Descriptive login function
platformLogin is concise, and it correctly handles encryption, method, and error handling. This ensures a secure, debuggable flow.


144-166: Refresh token approach
platformRefreshToken updates stored tokens. Consider concurrency scenarios where multiple refreshes might be triggered; a synchronization mechanism could help avoid race conditions.


234-290: Project secret handling
Requiring base64-encoded secrets is a good practice to avoid storing raw secrets in logs. This approach helps keep sensitive data safe.


314-366: Invite validation
Returning early if email is empty is a nice addition, avoiding unnecessary API calls. This pattern helps maintain data integrity.


368-371: Lightweight platformMe function
Fetching the logged-in user is uncomplicated, making it easy to incorporate user verification or guard logic in higher-level components.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (3)
src/lib/attestation.ts (1)

281-283: Consider passing explicitApiUrl to authenticate.
If you want to support custom API endpoints fully, you might consider passing explicitApiUrl to the authenticate function. Currently, authenticate does not take an explicitApiUrl argument; evaluate whether that is necessary for your use case.

README.md (1)

169-594: Documentation thoroughly covers new Developer Platform API usage.
This section is comprehensive and well-structured. As a minor enhancement, you could fix some punctuation issues flagged by the static analysis (e.g., removing or replacing “-” in place of repeated colons). Otherwise, it looks good for onboarding developers.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~281-~281: Loose punctuation mark.
Context: ...``` #### Developer State - developer: An object containing the current develo...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~292-~292: Loose punctuation mark.
Context: ...string): Promise`: Signs in a developer with the provided ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~293-~293: Loose punctuation mark.
Context: ...string): Promise`: Registers a new developer account with ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~294-~294: Loose punctuation mark.
Context: ...ly updated. - signOut(): Promise<void>: Signs out the current developer by remo...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~295-~295: Loose punctuation mark.
Context: ...l. - refetchDeveloper(): Promise<void>: Refreshes the developer's authenticatio...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~299-~299: Loose punctuation mark.
Context: ... Attestation Verification - pcrConfig: An object containing additional PCR0 ha...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~300-~300: Loose punctuation mark.
Context: ... to validate against. - getAttestation: Gets attestation from the enclave. - `a...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~301-~301: Loose punctuation mark.
Context: ...ation from the enclave. - authenticate: Authenticates an attestation document. ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~302-~302: Loose punctuation mark.
Context: ...on document. - parseAttestationForView: Parses an attestation document for view...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~303-~303: Loose punctuation mark.
Context: ...document for viewing. - awsRootCertDer: AWS root certificate in DER format. - `...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~304-~304: Loose punctuation mark.
Context: ... in DER format. - expectedRootCertHash: Expected hash of the AWS root certifica...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~305-~305: Loose punctuation mark.
Context: ...ertificate. - getAttestationDocument(): Gets and verifies an attestation docume...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~312-~312: Loose punctuation mark.
Context: ...on(name: string): Promise`: Creates a new organization with the giv...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~313-~313: Loose punctuation mark.
Context: ...rganizations(): Promise<Organization[]>`: Lists all organizations the developer h...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~314-~314: Loose punctuation mark.
Context: ...anization(orgId: string): Promise`: Deletes an organization (requires owner...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~330-~330: Loose punctuation mark.
Context: ...description?: string): Promise`: Creates a new project within an organiz...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~331-~331: Loose punctuation mark.
Context: ...ects(orgId: string): Promise<Project[]>`: Lists all projects within an organizati...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~332-~332: Loose punctuation mark.
Context: ...g; status?: string }): Promise: Updates project details. - deleteProje...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~333-~333: Loose punctuation mark.
Context: ...ring, projectId: string): Promise`: Deletes a project. Example: ```tsx con...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~354-~354: Loose punctuation mark.
Context: ...secret: string): Promise`: Creates a new secret for a project. The...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~355-~355: Loose punctuation mark.
Context: ...ctId: string): Promise<ProjectSecret[]>: Lists all secrets for a project. - del...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~356-~356: Loose punctuation mark.
Context: ...string, keyName: string): Promise`: Deletes a project secret. Example: ```...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~383-~383: Loose punctuation mark.
Context: ...jectId: string): Promise`: Gets email configuration for a project....

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~384-~384: Loose punctuation mark.
Context: ... EmailSettings): Promise`: Updates email configuration. Example: ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~404-~404: Loose punctuation mark.
Context: ...jectId: string): Promise: Gets OAuth settings for a project. - u...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~405-~405: Loose punctuation mark.
Context: ... OAuthSettings): Promise`: Updates OAuth configuration. Example: ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~428-~428: Loose punctuation mark.
Context: ...le?: string): Promise<{ code: string }>`: Creates an invitation to join an organi...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~429-~429: Loose punctuation mark.
Context: ... string): Promise<OrganizationMember[]>`: Lists all members of an organization. -...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~430-~430: Loose punctuation mark.
Context: ...e: string): Promise: Updates a member's role. - removeMembe...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~431-~431: Loose punctuation mark.
Context: ... string, userId: string): Promise`: Removes a member from the organization....

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~432-~432: Loose punctuation mark.
Context: ...ceptInvite(code: string): Promise`: Accepts an organization invitation. Ex...

(UNLIKELY_OPENING_PUNCTUATION)

src/lib/platformApi.ts (1)

1-372: Consistent API design and typing.
The structure effectively separates authentication, organization, project, and membership operations, maintaining clarity. If additional security or concurrency checks are needed (e.g., retries, token rotation logic), consider layering some retry/backoff mechanisms or expanded error handling for production use.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 046f849 and ac5a719.

⛔ Files ignored due to path filters (1)
  • bun.lockb is excluded by !**/bun.lockb
📒 Files selected for processing (13)
  • .gitignore (1 hunks)
  • README.md (2 hunks)
  • package.json (3 hunks)
  • src/lib/api.ts (2 hunks)
  • src/lib/attestation.ts (1 hunks)
  • src/lib/context.ts (1 hunks)
  • src/lib/developer.tsx (1 hunks)
  • src/lib/developerContext.ts (1 hunks)
  • src/lib/encryptedApi.ts (1 hunks)
  • src/lib/getAttestation.ts (3 hunks)
  • src/lib/platformApi.ts (1 hunks)
  • src/lib/util.ts (1 hunks)
  • vite.config.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (9)
  • src/lib/developerContext.ts
  • .gitignore
  • vite.config.ts
  • src/lib/encryptedApi.ts
  • src/lib/getAttestation.ts
  • src/lib/api.ts
  • src/lib/context.ts
  • package.json
  • src/lib/util.ts
🧰 Additional context used
🪛 LanguageTool
README.md

[uncategorized] ~281-~281: Loose punctuation mark.
Context: ...``` #### Developer State - developer: An object containing the current develo...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~292-~292: Loose punctuation mark.
Context: ...string): Promise`: Signs in a developer with the provided ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~293-~293: Loose punctuation mark.
Context: ...string): Promise`: Registers a new developer account with ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~294-~294: Loose punctuation mark.
Context: ...ly updated. - signOut(): Promise<void>: Signs out the current developer by remo...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~295-~295: Loose punctuation mark.
Context: ...l. - refetchDeveloper(): Promise<void>: Refreshes the developer's authenticatio...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~299-~299: Loose punctuation mark.
Context: ... Attestation Verification - pcrConfig: An object containing additional PCR0 ha...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~300-~300: Loose punctuation mark.
Context: ... to validate against. - getAttestation: Gets attestation from the enclave. - `a...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~301-~301: Loose punctuation mark.
Context: ...ation from the enclave. - authenticate: Authenticates an attestation document. ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~302-~302: Loose punctuation mark.
Context: ...on document. - parseAttestationForView: Parses an attestation document for view...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~303-~303: Loose punctuation mark.
Context: ...document for viewing. - awsRootCertDer: AWS root certificate in DER format. - `...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~304-~304: Loose punctuation mark.
Context: ... in DER format. - expectedRootCertHash: Expected hash of the AWS root certifica...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~305-~305: Loose punctuation mark.
Context: ...ertificate. - getAttestationDocument(): Gets and verifies an attestation docume...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~312-~312: Loose punctuation mark.
Context: ...on(name: string): Promise`: Creates a new organization with the giv...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~313-~313: Loose punctuation mark.
Context: ...rganizations(): Promise<Organization[]>`: Lists all organizations the developer h...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~314-~314: Loose punctuation mark.
Context: ...anization(orgId: string): Promise`: Deletes an organization (requires owner...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~330-~330: Loose punctuation mark.
Context: ...description?: string): Promise`: Creates a new project within an organiz...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~331-~331: Loose punctuation mark.
Context: ...ects(orgId: string): Promise<Project[]>`: Lists all projects within an organizati...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~332-~332: Loose punctuation mark.
Context: ...g; status?: string }): Promise: Updates project details. - deleteProje...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~333-~333: Loose punctuation mark.
Context: ...ring, projectId: string): Promise`: Deletes a project. Example: ```tsx con...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~354-~354: Loose punctuation mark.
Context: ...secret: string): Promise`: Creates a new secret for a project. The...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~355-~355: Loose punctuation mark.
Context: ...ctId: string): Promise<ProjectSecret[]>: Lists all secrets for a project. - del...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~356-~356: Loose punctuation mark.
Context: ...string, keyName: string): Promise`: Deletes a project secret. Example: ```...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~383-~383: Loose punctuation mark.
Context: ...jectId: string): Promise`: Gets email configuration for a project....

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~384-~384: Loose punctuation mark.
Context: ... EmailSettings): Promise`: Updates email configuration. Example: ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~404-~404: Loose punctuation mark.
Context: ...jectId: string): Promise: Gets OAuth settings for a project. - u...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~405-~405: Loose punctuation mark.
Context: ... OAuthSettings): Promise`: Updates OAuth configuration. Example: ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~428-~428: Loose punctuation mark.
Context: ...le?: string): Promise<{ code: string }>`: Creates an invitation to join an organi...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~429-~429: Loose punctuation mark.
Context: ... string): Promise<OrganizationMember[]>`: Lists all members of an organization. -...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~430-~430: Loose punctuation mark.
Context: ...e: string): Promise: Updates a member's role. - removeMembe...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~431-~431: Loose punctuation mark.
Context: ... string, userId: string): Promise`: Removes a member from the organization....

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~432-~432: Loose punctuation mark.
Context: ...ceptInvite(code: string): Promise`: Accepts an organization invitation. Ex...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~595-~595: A comma may be missing after the conjunctive/linking adverb ‘Currently’.
Context: ...oper.test.ts --env-file .env.local ``` Currently this build step requires npx because ...

(SENT_START_CONJUNCTIVE_LINKING_ADVERB_COMMA)

🔇 Additional comments (5)
src/lib/attestation.ts (3)

260-260: Confirm parameter usage alignment.
The newly introduced optional parameter explicitApiUrl aligns with the summary's description. Ensure that downstream calls and references across the codebase correctly handle the additional argument.


262-262: Validate function calls to fetchAttestationDocument.
You are now passing the new explicitApiUrl parameter to fetchAttestationDocument. Double-check that all callers have been updated accordingly.


265-266: Good fallback mechanism.
Using explicitApiUrl || getApiUrl() provides a clean override pattern for custom URLs. This is a sensible approach and helps maintain backward compatibility.

src/lib/developer.tsx (2)

1-50: Overall structure and context design look good.
The initialization of your React context, types, and imports demonstrates a clear separation of concerns. This fosters readability and maintainability.


397-409: Validate SSR usage.
You are setting and referencing window.__PLATFORM_API_URL__ inside a useEffect. This is fine in a client-only environment, but be sure to verify or guard against SSR environments where window is unavailable.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (3)
README.md (1)

197-198: Punctuation Suggestion:
Static analysis hints suggest that a comma might be needed after the conjunctive adverb “Currently” in the following text. Please double-check that sentence for clarity and consistency in punctuation.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~197-~197: A comma may be missing after the conjunctive/linking adverb ‘Currently’.
Context: ...oper.test.ts --env-file .env.local ``` Currently this build step requires npx because ...

(SENT_START_CONJUNCTIVE_LINKING_ADVERB_COMMA)

docs/PLATFORM.md (2)

111-121: Developer State Documentation:
The detailed breakdown of the developer object’s structure (including properties like loading, id, email, etc.) is very helpful.
Minor nitpick: Please review the punctuation in the bullet points as suggested by static analysis to ensure consistency.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~113-~113: Loose punctuation mark.
Context: ...``` #### Developer State - developer: An object containing the current develo...

(UNLIKELY_OPENING_PUNCTUATION)


5-5: Heading Level Consistency:
Markdownlint recommends that heading levels increment by one at a time. For example, changing

-### `OpenSecretDeveloper`
+## `OpenSecretDeveloper`

will ensure consistent heading structure across the document.

🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

5-5: Heading levels should only increment by one level at a time
Expected: h2; Actual: h3

(MD001, heading-increment)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ac5a719 and 3438619.

📒 Files selected for processing (2)
  • README.md (1 hunks)
  • docs/PLATFORM.md (1 hunks)
🧰 Additional context used
🪛 LanguageTool
docs/PLATFORM.md

[uncategorized] ~113-~113: Loose punctuation mark.
Context: ...``` #### Developer State - developer: An object containing the current develo...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~124-~124: Loose punctuation mark.
Context: ...string): Promise`: Signs in a developer with the provided ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~125-~125: Loose punctuation mark.
Context: ...string): Promise`: Registers a new developer account with ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~126-~126: Loose punctuation mark.
Context: ...ly updated. - signOut(): Promise<void>: Signs out the current developer by remo...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~127-~127: Loose punctuation mark.
Context: ...l. - refetchDeveloper(): Promise<void>: Refreshes the developer's authenticatio...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~131-~131: Loose punctuation mark.
Context: ... Attestation Verification - pcrConfig: An object containing additional PCR0 ha...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~132-~132: Loose punctuation mark.
Context: ... to validate against. - getAttestation: Gets attestation from the enclave. - `a...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~133-~133: Loose punctuation mark.
Context: ...ation from the enclave. - authenticate: Authenticates an attestation document. ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~134-~134: Loose punctuation mark.
Context: ...on document. - parseAttestationForView: Parses an attestation document for view...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~135-~135: Loose punctuation mark.
Context: ...document for viewing. - awsRootCertDer: AWS root certificate in DER format. - `...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~136-~136: Loose punctuation mark.
Context: ... in DER format. - expectedRootCertHash: Expected hash of the AWS root certifica...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~137-~137: Loose punctuation mark.
Context: ...ertificate. - getAttestationDocument(): Gets and verifies an attestation docume...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~144-~144: Loose punctuation mark.
Context: ...on(name: string): Promise`: Creates a new organization with the giv...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~145-~145: Loose punctuation mark.
Context: ...rganizations(): Promise<Organization[]>`: Lists all organizations the developer h...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~146-~146: Loose punctuation mark.
Context: ...anization(orgId: string): Promise`: Deletes an organization (requires owner...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~162-~162: Loose punctuation mark.
Context: ...description?: string): Promise`: Creates a new project within an organiz...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~163-~163: Loose punctuation mark.
Context: ...ects(orgId: string): Promise<Project[]>`: Lists all projects within an organizati...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~164-~164: Loose punctuation mark.
Context: ...g; status?: string }): Promise: Updates project details. - deleteProje...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~165-~165: Loose punctuation mark.
Context: ...ring, projectId: string): Promise`: Deletes a project. Example: ```tsx con...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~186-~186: Loose punctuation mark.
Context: ...secret: string): Promise`: Creates a new secret for a project. The...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~187-~187: Loose punctuation mark.
Context: ...ctId: string): Promise<ProjectSecret[]>: Lists all secrets for a project. - del...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~188-~188: Loose punctuation mark.
Context: ...string, keyName: string): Promise`: Deletes a project secret. Example: ```...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~215-~215: Loose punctuation mark.
Context: ...jectId: string): Promise`: Gets email configuration for a project....

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~216-~216: Loose punctuation mark.
Context: ... EmailSettings): Promise`: Updates email configuration. Example: ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~236-~236: Loose punctuation mark.
Context: ...jectId: string): Promise: Gets OAuth settings for a project. - u...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~237-~237: Loose punctuation mark.
Context: ... OAuthSettings): Promise`: Updates OAuth configuration. Example: ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~260-~260: Loose punctuation mark.
Context: ...le?: string): Promise<{ code: string }>`: Creates an invitation to join an organi...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~261-~261: Loose punctuation mark.
Context: ... string): Promise<OrganizationMember[]>`: Lists all members of an organization. -...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~262-~262: Loose punctuation mark.
Context: ...e: string): Promise: Updates a member's role. - removeMembe...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~263-~263: Loose punctuation mark.
Context: ... string, userId: string): Promise`: Removes a member from the organization....

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~264-~264: Loose punctuation mark.
Context: ...ceptInvite(code: string): Promise`: Accepts an organization invitation. Ex...

(UNLIKELY_OPENING_PUNCTUATION)

README.md

[uncategorized] ~197-~197: A comma may be missing after the conjunctive/linking adverb ‘Currently’.
Context: ...oper.test.ts --env-file .env.local ``` Currently this build step requires npx because ...

(SENT_START_CONJUNCTIVE_LINKING_ADVERB_COMMA)

🪛 markdownlint-cli2 (0.17.2)
docs/PLATFORM.md

5-5: Heading levels should only increment by one level at a time
Expected: h2; Actual: h3

(MD001, heading-increment)

🔇 Additional comments (7)
README.md (1)

192-197: New Test Command for Specific File/Case:
The added snippet clearly documents how to run a specific test case using Bun. This additional command is intuitive and should help developers quickly target tests for the developer platform API.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~197-~197: A comma may be missing after the conjunctive/linking adverb ‘Currently’.
Context: ...oper.test.ts --env-file .env.local ``` Currently this build step requires npx because ...

(SENT_START_CONJUNCTIVE_LINKING_ADVERB_COMMA)

docs/PLATFORM.md (6)

1-8: API Introduction Clarity:
The introduction section clearly outlines the purpose and scope of the Developer Platform API. The description is concise and sets the context effectively for what follows.

🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

5-5: Heading levels should only increment by one level at a time
Expected: h2; Actual: h3

(MD001, heading-increment)


9-22: Usage Example for OpenSecretDeveloper:
The code snippet demonstrating how to use the OpenSecretDeveloper component is well constructed. It clearly shows the required props (like apiUrl and optional pcrConfig), which helps users understand the setup process.


24-77: Developer Authentication Example:
The provided examples for handling developer authentication (login, registration, and error handling) are comprehensive. They illustrate practical usage with appropriate try/catch blocks and informative console messages.


80-92: Authentication State Check:
The snippet showing how to inspect the authentication state (using dev.developer.loading and dev.developer.developer) is clear and effectively demonstrates conditional rendering based on authentication state.


93-109: Hook Usage with useOpenSecretDeveloper:
The example usage of the useOpenSecretDeveloper hook is concise and to the point. It effectively communicates how to access developer state and provides a good reference for developers integrating the hook into their applications.


282-397: Complete Example – Developer Portal:
The complete example provided for the Developer Portal is excellent. It demonstrates an end-to-end integration of various API features (organization and project management, authentication, etc.) in a clear and comprehensive manner.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (4)
src/lib/developer.tsx (3)

397-409: Consider alternatives to global variable for API URL.

Setting a global variable __PLATFORM_API_URL__ on the window object might lead to namespace conflicts or pollution if multiple libraries do something similar.

- // Store the platform API URL in window for access from other modules
- if (typeof window !== 'undefined') {
-   window.__PLATFORM_API_URL__ = apiUrl;
- }
+ // Consider using a more isolated approach for sharing the API URL
+ // such as a module-level variable or a context-based solution

491-506: Inconsistent error handling in signOut method.

The signOut method catches errors and only logs them without rethrowing, unlike signIn and signUp methods which rethrow errors. This inconsistency could lead to silent failures that are difficult to debug.

  signOut: async () => {
    const refresh_token = window.localStorage.getItem("refresh_token");
    if (refresh_token) {
      try {
        await platformApi.platformLogout(refresh_token);
      } catch (error) {
        console.error("Error during logout:", error);
+       // Consider rethrowing the error for consistent error handling
+       // or document that logout errors are intentionally suppressed
      }
    }
    localStorage.removeItem("access_token");
    localStorage.removeItem("refresh_token");
    setAuth({
      loading: false,
      developer: undefined
    });
  },

383-541: Consider splitting this large component file.

At 541 lines, this file is quite large, which might make it harder to maintain. Consider splitting it into smaller, more focused files organized by functionality.

docs/PLATFORM.md (1)

5-22: Fix heading hierarchy in documentation.

The heading hierarchy jumps from h1 to h3, skipping h2. This can cause issues with document outline and accessibility.

-### `OpenSecretDeveloper`
+## `OpenSecretDeveloper`
🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

5-5: Heading levels should only increment by one level at a time
Expected: h2; Actual: h3

(MD001, heading-increment)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3438619 and 36b3d9f.

📒 Files selected for processing (3)
  • docs/PLATFORM.md (1 hunks)
  • src/lib/developer.tsx (1 hunks)
  • src/lib/index.ts (1 hunks)
🧰 Additional context used
🪛 LanguageTool
docs/PLATFORM.md

[uncategorized] ~113-~113: Loose punctuation mark.
Context: ..... } ``` #### Developer State - auth: An object containing the current develo...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~124-~124: Loose punctuation mark.
Context: ...string): Promise`: Signs in a developer with the provided ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~125-~125: Loose punctuation mark.
Context: ...string): Promise`: Registers a new developer account with ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~126-~126: Loose punctuation mark.
Context: ...ly updated. - signOut(): Promise<void>: Signs out the current developer by remo...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~127-~127: Loose punctuation mark.
Context: ...l. - refetchDeveloper(): Promise<void>: Refreshes the developer's authenticatio...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~131-~131: Loose punctuation mark.
Context: ... Attestation Verification - pcrConfig: An object containing additional PCR0 ha...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~132-~132: Loose punctuation mark.
Context: ... to validate against. - getAttestation: Gets attestation from the enclave. - `a...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~133-~133: Loose punctuation mark.
Context: ...ation from the enclave. - authenticate: Authenticates an attestation document. ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~134-~134: Loose punctuation mark.
Context: ...on document. - parseAttestationForView: Parses an attestation document for view...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~135-~135: Loose punctuation mark.
Context: ...document for viewing. - awsRootCertDer: AWS root certificate in DER format. - `...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~136-~136: Loose punctuation mark.
Context: ... in DER format. - expectedRootCertHash: Expected hash of the AWS root certifica...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~137-~137: Loose punctuation mark.
Context: ...ertificate. - getAttestationDocument(): Gets and verifies an attestation docume...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~144-~144: Loose punctuation mark.
Context: ...on(name: string): Promise`: Creates a new organization with the giv...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~145-~145: Loose punctuation mark.
Context: ...rganizations(): Promise<Organization[]>`: Lists all organizations the developer h...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~146-~146: Loose punctuation mark.
Context: ...anization(orgId: string): Promise`: Deletes an organization (requires owner...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~162-~162: Loose punctuation mark.
Context: ...description?: string): Promise`: Creates a new project within an organiz...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~163-~163: Loose punctuation mark.
Context: ...ects(orgId: string): Promise<Project[]>`: Lists all projects within an organizati...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~164-~164: Loose punctuation mark.
Context: ...g; status?: string }): Promise: Updates project details. - deleteProje...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~165-~165: Loose punctuation mark.
Context: ...ring, projectId: string): Promise`: Deletes a project. Example: ```tsx con...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~186-~186: Loose punctuation mark.
Context: ...secret: string): Promise`: Creates a new secret for a project. The...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~187-~187: Loose punctuation mark.
Context: ...ctId: string): Promise<ProjectSecret[]>: Lists all secrets for a project. - del...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~188-~188: Loose punctuation mark.
Context: ...string, keyName: string): Promise`: Deletes a project secret. Example: ```...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~215-~215: Loose punctuation mark.
Context: ...jectId: string): Promise`: Gets email configuration for a project....

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~216-~216: Loose punctuation mark.
Context: ... EmailSettings): Promise`: Updates email configuration. Example: ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~236-~236: Loose punctuation mark.
Context: ...jectId: string): Promise: Gets OAuth settings for a project. - u...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~237-~237: Loose punctuation mark.
Context: ... OAuthSettings): Promise`: Updates OAuth configuration. Example: ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~260-~260: Loose punctuation mark.
Context: ...le?: string): Promise<{ code: string }>`: Creates an invitation to join an organi...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~261-~261: Loose punctuation mark.
Context: ... string): Promise<OrganizationMember[]>`: Lists all members of an organization. -...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~262-~262: Loose punctuation mark.
Context: ...e: string): Promise: Updates a member's role. - removeMembe...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~263-~263: Loose punctuation mark.
Context: ... string, userId: string): Promise`: Removes a member from the organization....

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~264-~264: Loose punctuation mark.
Context: ...ceptInvite(code: string): Promise`: Accepts an organization invitation. Ex...

(UNLIKELY_OPENING_PUNCTUATION)

🪛 markdownlint-cli2 (0.17.2)
docs/PLATFORM.md

5-5: Heading levels should only increment by one level at a time
Expected: h2; Actual: h3

(MD001, heading-increment)

🔇 Additional comments (21)
src/lib/index.ts (3)

12-12: Export additions look good.

Good addition of the OpenSecretDeveloper exports, which aligns with the existing pattern of exporting providers and contexts.


14-16: Appropriate pluralization of comment and new hook export.

The comment change from singular to plural accurately reflects the addition of the new useOpenSecretDeveloper hook.


20-27: Well-structured type exports.

The type exports follow the existing pattern and provide a clean interface for consumers of the library. The grouping of related types enhances readability.

src/lib/developer.tsx (9)

26-35: Clean type definitions with appropriate exports.

The type definitions are clear and well-structured, providing a good foundation for the developer API. Reusing types from the platformApi module where appropriate is a good practice.


36-39: Well-defined authentication state type.

The OpenSecretDeveloperAuthState type clearly defines the authentication state structure with appropriate loading state and optional developer information.


41-316: Comprehensive and well-documented context type.

The context type definition is thorough and includes detailed JSDoc comments for each method, which is excellent for developer experience. The organization of methods by functionality (authentication, attestation, organization management, etc.) is logical and easy to follow.


318-364: Default context implementation provides good error messages.

The default context implementation appropriately throws errors with clear messages when methods are called outside of the provider. This helps developers identify misuse of the context.


460-480: Avoid storing tokens in localStorage for security.

Storing access and refresh tokens in localStorage is susceptible to XSS attacks. Consider using httpOnly cookies or secure storage strategies to help mitigate token theft.

- window.localStorage.setItem("access_token", access_token);
- window.localStorage.setItem("refresh_token", refresh_token);
+ // Consider storing tokens in httpOnly cookies or using secure, encrypted storage

399-402: Error handling for missing apiUrl is appropriate.

Good validation of the apiUrl parameter, ensuring that developers provide a valid API endpoint URL.


411-438: Good handling of authentication state initialization.

The fetchDeveloper function appropriately handles the cases where tokens are missing or the API call fails, which prevents potential issues during initialization.


440-454: Well-implemented attestation document retrieval.

The getAttestationDocument function includes proper error handling and follows a logical flow to fetch, authenticate, and parse the attestation document.


486-534: Comprehensive context value providing all necessary functionality.

The context value includes all the methods and properties defined in the context type, making the full API available to consumers.

docs/PLATFORM.md (9)

1-5: Good introduction to the Developer Platform API.

The introduction clearly explains the purpose and scope of the Developer Platform API.

🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

5-5: Heading levels should only increment by one level at a time
Expected: h2; Actual: h3

(MD001, heading-increment)


24-91: Clear authentication documentation with practical examples.

The authentication documentation provides clear examples of how to sign in, sign up, and sign out, including error handling best practices.


93-141: Comprehensive hook documentation.

The documentation for the useOpenSecretDeveloper hook clearly explains all available properties and methods, making it easy for developers to understand how to use the hook.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~113-~113: Loose punctuation mark.
Context: ..... } ``` #### Developer State - auth: An object containing the current develo...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~124-~124: Loose punctuation mark.
Context: ...string): Promise`: Signs in a developer with the provided ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~125-~125: Loose punctuation mark.
Context: ...string): Promise`: Registers a new developer account with ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~126-~126: Loose punctuation mark.
Context: ...ly updated. - signOut(): Promise<void>: Signs out the current developer by remo...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~127-~127: Loose punctuation mark.
Context: ...l. - refetchDeveloper(): Promise<void>: Refreshes the developer's authenticatio...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~131-~131: Loose punctuation mark.
Context: ... Attestation Verification - pcrConfig: An object containing additional PCR0 ha...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~132-~132: Loose punctuation mark.
Context: ... to validate against. - getAttestation: Gets attestation from the enclave. - `a...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~133-~133: Loose punctuation mark.
Context: ...ation from the enclave. - authenticate: Authenticates an attestation document. ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~134-~134: Loose punctuation mark.
Context: ...on document. - parseAttestationForView: Parses an attestation document for view...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~135-~135: Loose punctuation mark.
Context: ...document for viewing. - awsRootCertDer: AWS root certificate in DER format. - `...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~136-~136: Loose punctuation mark.
Context: ... in DER format. - expectedRootCertHash: Expected hash of the AWS root certifica...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~137-~137: Loose punctuation mark.
Context: ...ertificate. - getAttestationDocument(): Gets and verifies an attestation docume...

(UNLIKELY_OPENING_PUNCTUATION)


142-158: Well-structured organization management documentation.

The organization management section provides clear explanations and examples for creating, listing, and deleting organizations.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~144-~144: Loose punctuation mark.
Context: ...on(name: string): Promise`: Creates a new organization with the giv...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~145-~145: Loose punctuation mark.
Context: ...rganizations(): Promise<Organization[]>`: Lists all organizations the developer h...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~146-~146: Loose punctuation mark.
Context: ...anization(orgId: string): Promise`: Deletes an organization (requires owner...

(UNLIKELY_OPENING_PUNCTUATION)


160-182: Good project management documentation.

The project management section clearly explains how to create, list, update, and delete projects, with a helpful example that includes error handling.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~162-~162: Loose punctuation mark.
Context: ...description?: string): Promise`: Creates a new project within an organiz...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~163-~163: Loose punctuation mark.
Context: ...ects(orgId: string): Promise<Project[]>`: Lists all projects within an organizati...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~164-~164: Loose punctuation mark.
Context: ...g; status?: string }): Promise: Updates project details. - deleteProje...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~165-~165: Loose punctuation mark.
Context: ...ring, projectId: string): Promise`: Deletes a project. Example: ```tsx con...

(UNLIKELY_OPENING_PUNCTUATION)


184-211: Thorough secrets management documentation with encoding example.

The secrets management documentation includes important details about base64 encoding, with a concrete example of how to encode a string secret before storing it.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~186-~186: Loose punctuation mark.
Context: ...secret: string): Promise`: Creates a new secret for a project. The...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~187-~187: Loose punctuation mark.
Context: ...ctId: string): Promise<ProjectSecret[]>: Lists all secrets for a project. - del...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~188-~188: Loose punctuation mark.
Context: ...string, keyName: string): Promise`: Deletes a project secret. Example: ```...

(UNLIKELY_OPENING_PUNCTUATION)


213-232: Clear email and OAuth configuration documentation.

Both the email and OAuth configuration sections provide comprehensive documentation with clear examples of how to retrieve and update settings.

Also applies to: 234-256

🧰 Tools
🪛 LanguageTool

[uncategorized] ~215-~215: Loose punctuation mark.
Context: ...jectId: string): Promise`: Gets email configuration for a project....

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~216-~216: Loose punctuation mark.
Context: ... EmailSettings): Promise`: Updates email configuration. Example: ...

(UNLIKELY_OPENING_PUNCTUATION)


258-280: Comprehensive membership management documentation.

The membership management section covers all aspects of managing organization members, including invitations, role updates, and member removal.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~260-~260: Loose punctuation mark.
Context: ...le?: string): Promise<{ code: string }>`: Creates an invitation to join an organi...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~261-~261: Loose punctuation mark.
Context: ... string): Promise<OrganizationMember[]>`: Lists all members of an organization. -...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~262-~262: Loose punctuation mark.
Context: ...e: string): Promise: Updates a member's role. - removeMembe...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~263-~263: Loose punctuation mark.
Context: ... string, userId: string): Promise`: Removes a member from the organization....

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~264-~264: Loose punctuation mark.
Context: ...ceptInvite(code: string): Promise`: Accepts an organization invitation. Ex...

(UNLIKELY_OPENING_PUNCTUATION)


282-397: Excellent complete example.

The complete example provides a practical implementation that combines various aspects of the API, helping developers understand how everything fits together in a real application.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (5)
src/lib/test/integration/developer.test.ts (2)

37-38: Tokens in localStorage may pose security risks
Storing tokens in localStorage is prone to XSS attacks. Consider using httpOnly cookies or another secure approach to minimize exposure.

Also applies to: 54-55, 115-116, 179-180


41-41: loginError is never directly used
ESLint flags this variable as unused. If you need the error details, consider logging loginError.message; otherwise, remove or rename the parameter.

🧰 Tools
🪛 ESLint

[error] 41-41: 'loginError' is defined but never used.

(@typescript-eslint/no-unused-vars)

docs/PLATFORM.md (1)

5-5: Maintain consistent heading levels
Markdown guidelines advise incrementing headings by one level at a time. Consider changing ### to ## here for better readability and structure.

🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

5-5: Heading levels should only increment by one level at a time
Expected: h2; Actual: h3

(MD001, heading-increment)

src/lib/platformApi.ts (2)

146-147: Reevaluate storing tokens in localStorage
Retrieving and updating tokens from localStorage exposes them to potential XSS attacks. Consider a more secure alternative like httpOnly cookies.


317-318: Check consistency in HTTP methods for updates
You're using PATCH for project updates and PUT for OAuth settings. Consider clarifying or standardizing these approaches across all update endpoints for consistency.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 36b3d9f and 214ea6c.

📒 Files selected for processing (4)
  • docs/PLATFORM.md (1 hunks)
  • src/lib/developer.tsx (1 hunks)
  • src/lib/platformApi.ts (1 hunks)
  • src/lib/test/integration/developer.test.ts (1 hunks)
🧰 Additional context used
🪛 GitHub Check: test
src/lib/test/integration/developer.test.ts

[failure] 12-12: error: Test developer credentials must be set in .env.local

  at /home/runner/work/OpenSecret-SDK/OpenSecret-SDK/src/lib/test/integration/developer.test.ts:12:9
🪛 ESLint
src/lib/test/integration/developer.test.ts

[error] 41-41: 'loginError' is defined but never used.

(@typescript-eslint/no-unused-vars)


[error] 59-59: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 100-100: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 143-143: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 147-147: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 157-157: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 169-169: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 190-190: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 201-201: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 210-210: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 219-219: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 258-258: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 275-275: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 284-284: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 287-287: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 304-304: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 309-309: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 340-340: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 347-347: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 387-387: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 415-415: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 430-430: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 438-438: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 446-446: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 449-449: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 472-472: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 476-476: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 519-519: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 563-563: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 568-568: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 589-589: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 595-595: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 646-646: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 654-654: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 661-661: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 748-748: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 770-770: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 779-779: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 787-787: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 794-794: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 822-822: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 832-832: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 840-840: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 850-850: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 872-872: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 880-880: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 893-893: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 900-900: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 931-931: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 939-939: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 992-992: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1017-1017: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1025-1025: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1035-1035: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1043-1043: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1054-1054: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1087-1087: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1098-1098: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1156-1156: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1165-1165: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1190-1190: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1200-1200: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1284-1284: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1316-1316: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1329-1329: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1343-1343: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1356-1356: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1369-1369: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1380-1380: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1428-1428: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1451-1451: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1529-1529: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1545-1545: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1589-1589: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1608-1608: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1643-1643: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1656-1656: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1668-1668: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1684-1684: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1775-1775: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1815-1815: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)

🪛 LanguageTool
docs/PLATFORM.md

[uncategorized] ~113-~113: Loose punctuation mark.
Context: ..... } ``` #### Developer State - auth: An object containing the current develo...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~124-~124: Loose punctuation mark.
Context: ...string): Promise`: Signs in a developer with the provided ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~125-~125: Loose punctuation mark.
Context: ...string): Promise`: Registers a new developer account with ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~126-~126: Loose punctuation mark.
Context: ...ly updated. - signOut(): Promise<void>: Signs out the current developer by remo...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~127-~127: Loose punctuation mark.
Context: ...l. - refetchDeveloper(): Promise<void>: Refreshes the developer's authenticatio...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~131-~131: Loose punctuation mark.
Context: ... Attestation Verification - pcrConfig: An object containing additional PCR0 ha...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~132-~132: Loose punctuation mark.
Context: ... to validate against. - getAttestation: Gets attestation from the enclave. - `a...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~133-~133: Loose punctuation mark.
Context: ...ation from the enclave. - authenticate: Authenticates an attestation document. ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~134-~134: Loose punctuation mark.
Context: ...on document. - parseAttestationForView: Parses an attestation document for view...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~135-~135: Loose punctuation mark.
Context: ...document for viewing. - awsRootCertDer: AWS root certificate in DER format. - `...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~136-~136: Loose punctuation mark.
Context: ... in DER format. - expectedRootCertHash: Expected hash of the AWS root certifica...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~137-~137: Loose punctuation mark.
Context: ...ertificate. - getAttestationDocument(): Gets and verifies an attestation docume...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~144-~144: Loose punctuation mark.
Context: ...on(name: string): Promise`: Creates a new organization with the giv...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~145-~145: Loose punctuation mark.
Context: ...rganizations(): Promise<Organization[]>`: Lists all organizations the developer h...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~146-~146: Loose punctuation mark.
Context: ...anization(orgId: string): Promise`: Deletes an organization (requires owner...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~162-~162: Loose punctuation mark.
Context: ...description?: string): Promise`: Creates a new project within an organiz...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~163-~163: Loose punctuation mark.
Context: ...ects(orgId: string): Promise<Project[]>`: Lists all projects within an organizati...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~164-~164: Loose punctuation mark.
Context: ...g, projectId: string): Promise: Gets a single project by ID. - updateP...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~165-~165: Loose punctuation mark.
Context: ...g; status?: string }): Promise: Updates project details. - deleteProje...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~166-~166: Loose punctuation mark.
Context: ...ring, projectId: string): Promise`: Deletes a project. Example: ```tsx con...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~196-~196: Loose punctuation mark.
Context: ...secret: string): Promise`: Creates a new secret for a project. The...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~197-~197: Loose punctuation mark.
Context: ...ctId: string): Promise<ProjectSecret[]>: Lists all secrets for a project. - del...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~198-~198: Loose punctuation mark.
Context: ...string, keyName: string): Promise`: Deletes a project secret. Example: ```...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~225-~225: Loose punctuation mark.
Context: ...jectId: string): Promise`: Gets email configuration for a project....

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~226-~226: Loose punctuation mark.
Context: ... EmailSettings): Promise`: Updates email configuration. Example: ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~246-~246: Loose punctuation mark.
Context: ...jectId: string): Promise: Gets OAuth settings for a project. - u...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~247-~247: Loose punctuation mark.
Context: ... OAuthSettings): Promise`: Updates OAuth configuration. Example: ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~270-~270: Loose punctuation mark.
Context: ...le?: string): Promise<{ code: string }>`: Creates an invitation to join an organi...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~271-~271: Loose punctuation mark.
Context: ... string): Promise<OrganizationMember[]>`: Lists all members of an organization. -...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~272-~272: Loose punctuation mark.
Context: ...e: string): Promise: Updates a member's role. - removeMembe...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~273-~273: Loose punctuation mark.
Context: ... string, userId: string): Promise`: Removes a member from the organization....

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~274-~274: Loose punctuation mark.
Context: ...ceptInvite(code: string): Promise`: Accepts an organization invitation. Ex...

(UNLIKELY_OPENING_PUNCTUATION)

🪛 markdownlint-cli2 (0.17.2)
docs/PLATFORM.md

5-5: Heading levels should only increment by one level at a time
Expected: h2; Actual: h3

(MD001, heading-increment)

🔇 Additional comments (4)
src/lib/test/integration/developer.test.ts (2)

11-13: Ensure environment variables are defined
If any of TEST_DEVELOPER_EMAIL, TEST_DEVELOPER_PASSWORD, or TEST_DEVELOPER_NAME is missing, the tests throw an error. Consider providing defaults, skipping these tests, or using a mock approach to prevent pipeline failures when environment variables are absent.

🧰 Tools
🪛 GitHub Check: test

[failure] 12-12: error: Test developer credentials must be set in .env.local

  at /home/runner/work/OpenSecret-SDK/OpenSecret-SDK/src/lib/test/integration/developer.test.ts:12:9

59-59: Use a more specific error type instead of any
This point was previously raised. Replace (error: any) with unknown or a custom interface to improve clarity and avoid ESLint warnings. For example:

- catch (error: any) {
+ catch (error: unknown) {
  if (error instanceof Error) {
    console.error(error.message);
  }
}

Also applies to: 100-100, 143-143, 147-147, 157-157, 169-169, 190-190, 201-201, 210-210, 219-219, 258-258, 275-275, 284-284, 287-287, 304-304, 309-309, 340-340, 347-347, 387-387, 415-415, 430-430, 438-438, 446-446, 449-449, 472-472, 476-476, 519-519, 563-563, 568-568, 589-589, 595-595, 646-646, 654-654, 661-661, 748-748, 770-770, 779-779, 787-787, 794-794, 822-822, 832-832, 840-840, 850-850, 872-872, 880-880, 893-893, 900-900, 931-931, 939-939, 992-992, 1017-1017, 1025-1025, 1035-1035, 1043-1043, 1054-1054, 1087-1087, 1098-1098, 1156-1156, 1165-1165, 1190-1190, 1200-1200, 1284-1284, 1316-1316, 1329-1329, 1343-1343, 1356-1356, 1369-1369, 1380-1380, 1428-1428, 1451-1451, 1529-1529, 1545-1545, 1589-1589, 1608-1608, 1643-1643, 1656-1656, 1668-1668, 1684-1684, 1775-1775, 1815-1815

🧰 Tools
🪛 ESLint

[error] 59-59: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)

src/lib/developer.tsx (2)

472-473: Reusing localStorage for tokens can be insecure
This is a known security concern. For long-lived sessions, httpOnly cookies or secure storage strategies reduce exposure to XSS vulnerabilities.


477-478: Replace any with a more specific error type
This repeats a prior suggestion. Using unknown or a custom type clarifies handling in catch blocks and complies with ESLint rules.

Also applies to: 490-491

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (23)
docs/PLATFORM.md (4)

5-8: Heading Level Consistency

The header for the OpenSecretDeveloper component is currently at the third level (###). Since the document starts with an H1 title (“# Developer Platform API”), it is recommended to use H2 for major subsections. For consistency and to satisfy markdownlint guidelines, consider changing this heading from ### to ##.

Proposed diff:

-### `OpenSecretDeveloper`
+## `OpenSecretDeveloper`
🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

5-5: Heading levels should only increment by one level at a time
Expected: h2; Actual: h3

(MD001, heading-increment)


111-121: Developer State Documentation – Consider Punctuation Consistency

The “Developer State” section lists properties and sub-properties clearly. A minor nitpick: to enhance readability and ensure consistency in documentation, consider standardizing the punctuation (for example, ensuring a uniform ending such as a period for each bullet point).

🧰 Tools
🪛 LanguageTool

[uncategorized] ~113-~113: Loose punctuation mark.
Context: ..... } ``` #### Developer State - auth: An object containing the current develo...

(UNLIKELY_OPENING_PUNCTUATION)


122-128: Developer Authentication Methods Documentation

The descriptions of the authentication methods (such as signIn, signUp, signOut, and refetchDeveloper) are comprehensive and clear. Similar to the previous section, a small suggestion is to standardize the punctuation and formatting (e.g., ending each method description with a period) to improve visual consistency across the document.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~124-~124: Loose punctuation mark.
Context: ...string): Promise`: Signs in a developer with the provided ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~125-~125: Loose punctuation mark.
Context: ...string): Promise`: Registers a new developer account with ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~126-~126: Loose punctuation mark.
Context: ...ly updated. - signOut(): Promise<void>: Signs out the current developer by remo...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~127-~127: Loose punctuation mark.
Context: ...l. - refetchDeveloper(): Promise<void>: Refreshes the developer's authenticatio...

(UNLIKELY_OPENING_PUNCTUATION)


111-137: Minor Formatting and Punctuation Consistency

There are several static analysis hints regarding loose punctuation in the API method lists (e.g., in sections describing authentication methods and attestation verification). While these are non-critical, consider reviewing the punctuation (such as the use or omission of ending periods) to ensure a consistent and polished documentation style throughout the file.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~113-~113: Loose punctuation mark.
Context: ..... } ``` #### Developer State - auth: An object containing the current develo...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~124-~124: Loose punctuation mark.
Context: ...string): Promise`: Signs in a developer with the provided ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~125-~125: Loose punctuation mark.
Context: ...string): Promise`: Registers a new developer account with ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~126-~126: Loose punctuation mark.
Context: ...ly updated. - signOut(): Promise<void>: Signs out the current developer by remo...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~127-~127: Loose punctuation mark.
Context: ...l. - refetchDeveloper(): Promise<void>: Refreshes the developer's authenticatio...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~131-~131: Loose punctuation mark.
Context: ... Attestation Verification - pcrConfig: An object containing additional PCR0 ha...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~132-~132: Loose punctuation mark.
Context: ... to validate against. - getAttestation: Gets attestation from the enclave. - `a...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~133-~133: Loose punctuation mark.
Context: ...ation from the enclave. - authenticate: Authenticates an attestation document. ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~134-~134: Loose punctuation mark.
Context: ...on document. - parseAttestationForView: Parses an attestation document for view...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~135-~135: Loose punctuation mark.
Context: ...document for viewing. - awsRootCertDer: AWS root certificate in DER format. - `...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~136-~136: Loose punctuation mark.
Context: ... in DER format. - expectedRootCertHash: Expected hash of the AWS root certifica...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~137-~137: Loose punctuation mark.
Context: ...ertificate. - getAttestationDocument(): Gets and verifies an attestation docume...

(UNLIKELY_OPENING_PUNCTUATION)

src/lib/encryptedApi.ts (3)

26-34: Potential false positive in URL detection
Using url.includes('/platform/') might match unintended endpoints if the substring appears elsewhere in the URL. Consider a more robust or explicit check, such as matching a known base path constant, to avoid accidental collisions.


53-53: Log message improvement
Consider including additional context for easier debugging (e.g., response headers) while ensuring no PII is logged.


95-96: Attestation renewal condition
Re-requesting a fresh attestation on invalid session data is valid. Add a safeguard (e.g., a retry limit) to avoid infinite attempts if attestation fails repeatedly.

src/lib/platformApi.ts (16)

17-24: Organization data structure
Optional fields like role and timestamps are handy, but ensure a consistent timestamp format (e.g., ISO 8601) for easier processing.


40-44: Organization type
Minimal organization fields can cause duplication if also represented by PlatformOrg. Unify them to avoid confusion.


61-66: Project settings
Record<string, unknown> offers flexibility but can obscure typed usage. Document known keys or provide partial types for clarity.


82-87: OAuth toggles
Allowing selective OAuth provider activation is helpful. Validate configuration completeness before enabling a provider.


89-92: Organization members
Consider tracking if a member's invitation is accepted or pending to reflect membership status accurately.


94-98: Global platform API URL
Using a global variable can cause unexpected state issues in SSR or multi-tenant setups. Consider passing it as a parameter instead.


118-133: Platform registration
The optional name field is useful for username flexibility. Verify how the backend handles omitted or null name values.


192-198: List organizations
Consider implementing pagination to avoid large response payloads for organizations.


208-219: Create project
Optional description is a nice addition. Consider maximum size limits to avoid overly large descriptions.


221-227: List projects
Similarly, consider paginating or limiting results if the number of projects is large.


237-247: Update project
Partially updating fields is flexible. Document how omitted fields behave on the server side.


257-270: Base64 validation utility
Simple regex-based check. For maximum reliability, consider using a trusted library for base64 validation.


335-342: Get OAuth settings
No immediate issues; just confirm secrets are not displayed.


344-354: Update OAuth settings
Consider restricting updates to high-risk fields like client_id or client_secret to administrator-only.


374-380: List organization members
If the list is large, anonymize or limit personal info to maintain user privacy.


402-408: Accept invite
Consider restricting each invite code to a single usage.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 214ea6c and a9edb77.

📒 Files selected for processing (3)
  • docs/PLATFORM.md (1 hunks)
  • src/lib/encryptedApi.ts (4 hunks)
  • src/lib/platformApi.ts (1 hunks)
🧰 Additional context used
🪛 LanguageTool
docs/PLATFORM.md

[uncategorized] ~113-~113: Loose punctuation mark.
Context: ..... } ``` #### Developer State - auth: An object containing the current develo...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~124-~124: Loose punctuation mark.
Context: ...string): Promise`: Signs in a developer with the provided ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~125-~125: Loose punctuation mark.
Context: ...string): Promise`: Registers a new developer account with ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~126-~126: Loose punctuation mark.
Context: ...ly updated. - signOut(): Promise<void>: Signs out the current developer by remo...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~127-~127: Loose punctuation mark.
Context: ...l. - refetchDeveloper(): Promise<void>: Refreshes the developer's authenticatio...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~131-~131: Loose punctuation mark.
Context: ... Attestation Verification - pcrConfig: An object containing additional PCR0 ha...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~132-~132: Loose punctuation mark.
Context: ... to validate against. - getAttestation: Gets attestation from the enclave. - `a...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~133-~133: Loose punctuation mark.
Context: ...ation from the enclave. - authenticate: Authenticates an attestation document. ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~134-~134: Loose punctuation mark.
Context: ...on document. - parseAttestationForView: Parses an attestation document for view...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~135-~135: Loose punctuation mark.
Context: ...document for viewing. - awsRootCertDer: AWS root certificate in DER format. - `...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~136-~136: Loose punctuation mark.
Context: ... in DER format. - expectedRootCertHash: Expected hash of the AWS root certifica...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~137-~137: Loose punctuation mark.
Context: ...ertificate. - getAttestationDocument(): Gets and verifies an attestation docume...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~144-~144: Loose punctuation mark.
Context: ...on(name: string): Promise`: Creates a new organization with the giv...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~145-~145: Loose punctuation mark.
Context: ...rganizations(): Promise<Organization[]>`: Lists all organizations the developer h...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~146-~146: Loose punctuation mark.
Context: ...anization(orgId: string): Promise`: Deletes an organization (requires owner...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~162-~162: Loose punctuation mark.
Context: ...description?: string): Promise`: Creates a new project within an organiz...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~163-~163: Loose punctuation mark.
Context: ...ects(orgId: string): Promise<Project[]>`: Lists all projects within an organizati...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~164-~164: Loose punctuation mark.
Context: ...g, projectId: string): Promise: Gets a single project by ID. - updateP...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~165-~165: Loose punctuation mark.
Context: ...g; status?: string }): Promise: Updates project details. - deleteProje...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~166-~166: Loose punctuation mark.
Context: ...ring, projectId: string): Promise`: Deletes a project. Example: ```tsx con...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~196-~196: Loose punctuation mark.
Context: ...secret: string): Promise`: Creates a new secret for a project. The...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~197-~197: Loose punctuation mark.
Context: ...ctId: string): Promise<ProjectSecret[]>: Lists all secrets for a project. - del...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~198-~198: Loose punctuation mark.
Context: ...string, keyName: string): Promise`: Deletes a project secret. Example: ```...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~225-~225: Loose punctuation mark.
Context: ...jectId: string): Promise`: Gets email configuration for a project....

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~226-~226: Loose punctuation mark.
Context: ... EmailSettings): Promise`: Updates email configuration. Example: ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~246-~246: Loose punctuation mark.
Context: ...jectId: string): Promise: Gets OAuth settings for a project. - u...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~247-~247: Loose punctuation mark.
Context: ... OAuthSettings): Promise`: Updates OAuth configuration. Example: ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~270-~270: Loose punctuation mark.
Context: ...le?: string): Promise<{ code: string }>`: Creates an invitation to join an organi...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~271-~271: Loose punctuation mark.
Context: ... string): Promise<OrganizationMember[]>`: Lists all members of an organization. -...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~272-~272: Loose punctuation mark.
Context: ...e: string): Promise: Updates a member's role. - removeMembe...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~273-~273: Loose punctuation mark.
Context: ... string, userId: string): Promise`: Removes a member from the organization....

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~274-~274: Loose punctuation mark.
Context: ...ceptInvite(code: string): Promise`: Accepts an organization invitation. Ex...

(UNLIKELY_OPENING_PUNCTUATION)

🪛 markdownlint-cli2 (0.17.2)
docs/PLATFORM.md

5-5: Heading levels should only increment by one level at a time
Expected: h2; Actual: h3

(MD001, heading-increment)

🔇 Additional comments (39)
docs/PLATFORM.md (14)

1-4: Clear Introduction and Context Provided

The title and opening paragraph effectively introduce the Developer Platform API and explain its purpose. This section sets a solid context for the details that follow.


9-22: Usage Example for OpenSecretDeveloper Component

The code snippet illustrating the usage of the OpenSecretDeveloper component is clear and well-structured. It correctly demonstrates initializing the provider with required props such as apiUrl and an optional pcrConfig.


24-28: Developer Authentication Section Introduction

The introductory text for the Developer Authentication section is concise and informative. It clearly outlines the purpose of the useOpenSecretDeveloper hook in facilitating authentication.


29-78: DeveloperLogin Component Example is Robust

The DeveloperLogin component example demonstrates the usage of authentication methods (signIn, signUp, and signOut) with appropriate error handling via try-catch. The inline comments help clarify the intent at each step. This snippet is well-written for demonstration purposes.


80-92: Authentication State Check Example

The sample code that checks whether the developer is authenticated (by examining dev.auth.loading and dev.auth.developer) is both clear and practical. It serves as a useful reference for consumers of the SDK.


93-110: Usage Example for useOpenSecretDeveloper in PlatformManagement

The code snippet provided under the useOpenSecretDeveloper section clearly shows how to access the hook and extract authentication details. It is straightforward and serves its documentation purpose well.


129-141: Attestation Verification Methods Overview

The detailed list of attestation-related methods (e.g., getAttestation, authenticate, and parseAttestationForView) provides clear insight into the attestation process. The step-by-step description under getAttestationDocument() is especially useful.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~131-~131: Loose punctuation mark.
Context: ... Attestation Verification - pcrConfig: An object containing additional PCR0 ha...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~132-~132: Loose punctuation mark.
Context: ... to validate against. - getAttestation: Gets attestation from the enclave. - `a...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~133-~133: Loose punctuation mark.
Context: ...ation from the enclave. - authenticate: Authenticates an attestation document. ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~134-~134: Loose punctuation mark.
Context: ...on document. - parseAttestationForView: Parses an attestation document for view...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~135-~135: Loose punctuation mark.
Context: ...document for viewing. - awsRootCertDer: AWS root certificate in DER format. - `...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~136-~136: Loose punctuation mark.
Context: ... in DER format. - expectedRootCertHash: Expected hash of the AWS root certifica...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~137-~137: Loose punctuation mark.
Context: ...ertificate. - getAttestationDocument(): Gets and verifies an attestation docume...

(UNLIKELY_OPENING_PUNCTUATION)


142-158: Organization Management Section is Well-Documented

The section detailing organization management functions is clear, and the accompanying code example for creating an organization is concise. This provides a good reference for developers on how to execute these operations using the SDK.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~144-~144: Loose punctuation mark.
Context: ...on(name: string): Promise`: Creates a new organization with the giv...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~145-~145: Loose punctuation mark.
Context: ...rganizations(): Promise<Organization[]>`: Lists all organizations the developer h...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~146-~146: Loose punctuation mark.
Context: ...anization(orgId: string): Promise`: Deletes an organization (requires owner...

(UNLIKELY_OPENING_PUNCTUATION)


160-193: Project Management Methods and Examples are Comprehensive

The documentation for project management covers creation, listing, retrieval, updating, and deletion of projects with clear examples. The inline comments in the code examples enhance understanding.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~162-~162: Loose punctuation mark.
Context: ...description?: string): Promise`: Creates a new project within an organiz...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~163-~163: Loose punctuation mark.
Context: ...ects(orgId: string): Promise<Project[]>`: Lists all projects within an organizati...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~164-~164: Loose punctuation mark.
Context: ...g, projectId: string): Promise: Gets a single project by ID. - updateP...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~165-~165: Loose punctuation mark.
Context: ...g; status?: string }): Promise: Updates project details. - deleteProje...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~166-~166: Loose punctuation mark.
Context: ...ring, projectId: string): Promise`: Deletes a project. Example: ```tsx con...

(UNLIKELY_OPENING_PUNCTUATION)


194-221: Project Secrets Management is Clear and Actionable

The explanation of project secrets management methods, along with a code example that includes base64 encoding of the secret, is practical and detailed. This section meets the documentation needs effectively.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~196-~196: Loose punctuation mark.
Context: ...secret: string): Promise`: Creates a new secret for a project. The...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~197-~197: Loose punctuation mark.
Context: ...ctId: string): Promise<ProjectSecret[]>: Lists all secrets for a project. - del...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~198-~198: Loose punctuation mark.
Context: ...string, keyName: string): Promise`: Deletes a project secret. Example: ```...

(UNLIKELY_OPENING_PUNCTUATION)


223-242: Email Configuration Documentation is Well-Structured

The email configuration section, including both getEmailSettings and updateEmailSettings, explains the methods clearly and provides a clear example for updating email settings.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~225-~225: Loose punctuation mark.
Context: ...jectId: string): Promise`: Gets email configuration for a project....

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~226-~226: Loose punctuation mark.
Context: ... EmailSettings): Promise`: Updates email configuration. Example: ...

(UNLIKELY_OPENING_PUNCTUATION)


244-267: OAuth Configuration Section Provides Clear Guidance

The OAuth configuration methods and the provided example (which demonstrates enabling/disabling OAuth providers and configuring settings) are comprehensive and clearly explained.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~246-~246: Loose punctuation mark.
Context: ...jectId: string): Promise: Gets OAuth settings for a project. - u...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~247-~247: Loose punctuation mark.
Context: ... OAuthSettings): Promise`: Updates OAuth configuration. Example: ...

(UNLIKELY_OPENING_PUNCTUATION)


268-291: Developer Membership Management is Thoroughly Documented

The membership management section covers inviting, listing, updating, and removing organization members, along with a clear, standalone example. This detailed explanation aids in understanding the full range of membership operations.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~270-~270: Loose punctuation mark.
Context: ...le?: string): Promise<{ code: string }>`: Creates an invitation to join an organi...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~271-~271: Loose punctuation mark.
Context: ... string): Promise<OrganizationMember[]>`: Lists all members of an organization. -...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~272-~272: Loose punctuation mark.
Context: ...e: string): Promise: Updates a member's role. - removeMembe...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~273-~273: Loose punctuation mark.
Context: ... string, userId: string): Promise`: Removes a member from the organization....

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~274-~274: Loose punctuation mark.
Context: ...ceptInvite(code: string): Promise`: Accepts an organization invitation. Ex...

(UNLIKELY_OPENING_PUNCTUATION)


292-418: Complete Example: Comprehensive Integration Demonstration

The complete example that integrates the Developer Portal within a React application is extensive and well-structured. It effectively demonstrates asynchronous operations, state management, and real-time data updates (e.g., loading organizations and projects). The inline comments improve clarity and usability.

src/lib/encryptedApi.ts (2)

4-4: Well-structured import
Your newly introduced import for platformRefreshToken is consistent with the domain separation, ensuring platform-specific logic remains in platformApi.ts.


85-92: Conditional attestation logic
Using explicitApiUrl in platform calls decouples logic well, but ensure window.__PLATFORM_API_URL__ is reliably set or gracefully handled in non-browser contexts.

src/lib/platformApi.ts (23)

1-2: New import usage
Imports from encryptedApi appear consistent with the overall encryption flow.


3-10: Structured login response interface
Defining PlatformLoginResponse makes it clear how login results are structured, reducing the risk of runtime mismatches.


12-15: Refresh response interface
Explicitly naming both access and refresh tokens in PlatformRefreshResponse ensures reliable usage patterns for token handling.


26-33: User data structure
email_verified is an important flag. Confirm that created_at and updated_at share a unified format across all user-related data.


35-38: MeResponse
Combining user and organizations simplifies client-side logic. Ensure each organization object follows the same schema as PlatformOrg.


46-53: Project interface
client_id could be security-sensitive if exposed publicly. Confirm that it's safe to display or log.


55-59: Secret handling
This standardized metadata structure eases secret management. Keep security controls in place to prevent accidental exposure.


68-72: Email settings
Validate email_verification_url to prevent redirect-based attacks or malformed links.


74-80: OAuth provider settings
Ensure each redirect_url strictly matches your registered redirect domains to avoid open redirect issues.


135-143: Logout endpoint
Confirm tokens are invalidated server-side for a complete logout, not just removed from the client.


145-181: Platform refresh
Your encrypted refresh flow seems well secured. Confirm if a 'logout all sessions' server method invalidates existing refresh tokens.


183-190: Create organization
Straightforward usage of authenticatedApiCall. Looks fine.


200-206: Organization deletion
Check for cleanup or reassignment of child resources (e.g., projects, secrets) to avoid orphaned data.


229-235: Get project
Simple GET request. No issues evident.


249-255: Delete project
Ensure that any secrets or data belonging to the project are cleaned up appropriately.


272-289: Create project secret
Verifying base64 is essential. Also consider limiting size or scanning the secret contents if relevant to security.


302-312: Delete project secret
Check for 404 or other upstream errors if the secret does not exist.


314-321: Retrieve email settings
Be mindful not to expose provider credentials in the JSON response.


323-333: Update email settings
Same caution as retrieval: protect or redact sensitive credentials in logs or payloads.


356-372: Invite developer
Good to see validation for empty email strings. Ensure the backend enforces rate limits to prevent spam invites.


382-392: Update member role
Ensure the API requires appropriate admin privileges before changing roles.


394-400: Remove member
Watch for scenarios where the last remaining admin is accidentally removed.


410-413: platformMe()
Simple retrieval of the active user's info. Caching might help if called frequently.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (2)
src/lib/test/integration/developer.test.ts (2)

41-41: ⚠️ Potential issue

Remove unused 'loginError' parameter.

The 'loginError' parameter is defined but never used, which triggers an ESLint warning.

-  } catch (loginError) {
+  } catch (error) {
    console.warn("Login failed, attempting to register the user");
🧰 Tools
🪛 ESLint

[error] 41-41: 'loginError' is defined but never used.

(@typescript-eslint/no-unused-vars)


59-59: 🛠️ Refactor suggestion

Use more specific types instead of any for error parameters.

Many catch blocks use catch (error: any). Consider a more precise type, such as unknown or a custom error interface. This clarifies error handling and avoids ESLint warnings.

-    } catch (registerError: any) {
+    } catch (registerError: unknown) {
      if (
-        registerError.message.includes("Email already registered") ||
-        registerError.message.includes("User already exists")
+        registerError instanceof Error && 
+        (registerError.message.includes("Email already registered") ||
+        registerError.message.includes("User already exists"))
      ) {
        console.log("User already registered, retrying login");

This pattern should be applied to all catch blocks in the file that use the any type.

🧰 Tools
🪛 ESLint

[error] 59-59: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)

🧹 Nitpick comments (13)
src/lib/encryptedApi.ts (3)

26-34: Improve conditional platform token refresh logging.

The code correctly differentiates between platform and regular API calls for token refresh, but includes several console.log statements that should be removed or made configurable in production code.

-        console.log("Using platform refresh token");
+        // Consider using a debug flag: if (DEBUG_MODE) console.log("Using platform refresh token");
         await platformRefreshToken();
       } else {
-        console.log("Using regular refresh token");
+        // Consider using a debug flag: if (DEBUG_MODE) console.log("Using regular refresh token");
         await refreshToken();
       }

53-53: Add more descriptive log message.

The log message for 401 errors is good, but could be more consistent with the platform/regular API differentiation pattern established above.

-        console.log(`Received 401 for URL ${url}, attempting to refresh token`);
+        console.log(`Received 401 for ${url.includes("/platform/") ? "platform" : "regular"} API URL ${url}, attempting to refresh token`);

85-91: Properly type the global window property for TypeScript.

The code correctly checks for window existence, but the __PLATFORM_API_URL__ property is not typed in the Window interface which could lead to TypeScript errors.

Consider adding a TypeScript declaration to properly type the window object:

// Add this to a global declaration file (e.g., types.d.ts)
declare global {
  interface Window {
    __PLATFORM_API_URL__?: string;
  }
}
src/lib/test/integration/developer.test.ts (3)

11-13: Improve error handling for missing environment variables.

The test fails with a basic error when environment variables are missing. Consider providing a more helpful error message with instructions on how to configure the test environment.

if (!TEST_DEVELOPER_EMAIL || !TEST_DEVELOPER_PASSWORD || !TEST_DEVELOPER_NAME) {
-  throw new Error("Test developer credentials must be set in .env.local");
+  throw new Error(
+    "Test developer credentials must be set in .env.local\n" +
+    "Please add the following variables to your .env.local file:\n" +
+    "[email protected]\n" +
+    "VITE_TEST_DEVELOPER_PASSWORD=your-test-password\n" +
+    "VITE_TEST_DEVELOPER_NAME=Your Test Name"
+  );
}
🧰 Tools
🪛 GitHub Check: test

[failure] 12-12: error: Test developer credentials must be set in .env.local

  at /home/runner/work/OpenSecret-SDK/OpenSecret-SDK/src/lib/test/integration/developer.test.ts:12:9

1-4: Consider splitting the test file for better maintainability.

This test file is extremely long (over 2000 lines) and covers multiple distinct functional areas. Consider splitting it into separate test files by feature area (authentication, organizations, projects, secrets) for better maintainability and test isolation.

For example:

  • auth.test.ts for authentication tests
  • organization.test.ts for organization management tests
  • project.test.ts for project management tests
  • secret.test.ts for secret management tests

This would make the tests more manageable and easier to run individually.

🧰 Tools
🪛 GitHub Actions: Library Tests

[error] 1-1: Unhandled error between tests


526-532: Extract test setup into reusable helper functions.

The test code has significant duplication in setup patterns. For instance, organization creation for testing is repeated in many tests. Consider extracting common setup and teardown operations into helper functions.

For example:

// Helper function to create a test organization and clean it up after the test
async function withTestOrganization(testFn: (org: Organization) => Promise<void>) {
  // Create a test organization
  const orgName = `Test Org ${Date.now()}`;
  const org = await platformApi.createOrganization(orgName);
  
  try {
    // Run the test with the created organization
    await testFn(org);
  } finally {
    // Clean up the organization
    await platformApi.deleteOrganization(org.id.toString());
  }
}

// Usage in a test
test("Platform API URL validation", async () => {
  await withTestOrganization(async (org) => {
    // Test code using the organization
    const apiUrl = process.env.VITE_OPEN_SECRET_API_URL;
    expect(apiUrl).toBeDefined();
    // ...more test code
  });
});
src/lib/developer.tsx (1)

537-538: Use consistent window.localStorage access.

The code uses window.localStorage in some places and localStorage directly in others. For consistency and to avoid potential issues in different environments, use the same approach throughout.

-      localStorage.removeItem("access_token");
-      localStorage.removeItem("refresh_token");
+      window.localStorage.removeItem("access_token");
+      window.localStorage.removeItem("refresh_token");
docs/PLATFORM.md (2)

188-199: Document security considerations for token storage.

While explaining how tokens are stored in localStorage, it would be helpful to mention that this approach has security implications and might change in future versions.

When a developer successfully logs in or registers, the authentication tokens are stored in localStorage and managed by the SDK. The `OpenSecretDeveloper` provider automatically detects these tokens and loads the developer profile. You can check the authentication state using the `auth` property:

+> **Note**: Storing tokens in localStorage has security implications as it makes them vulnerable to XSS attacks. A more secure token storage mechanism is planned for future releases of the SDK.
+

348-350: Add note about secret encoding requirement.

The documentation mentions that secrets must be base64 encoded, but it could be helpful to explain why this encoding is necessary.

- `createProjectSecret(orgId: string, projectId: string, keyName: string, secret: string): Promise<ProjectSecret>`: Creates a new secret for a project. The secret must be base64 encoded.
+ `createProjectSecret(orgId: string, projectId: string, keyName: string, secret: string): Promise<ProjectSecret>`: Creates a new secret for a project. The secret must be base64 encoded to ensure proper handling of binary data and special characters.
🧰 Tools
🪛 LanguageTool

[uncategorized] ~348-~348: Loose punctuation mark.
Context: ...secret: string): Promise`: Creates a new secret for a project. The...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~349-~349: Loose punctuation mark.
Context: ...ctId: string): Promise<ProjectSecret[]>: Lists all secrets for a project. - del...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~350-~350: Loose punctuation mark.
Context: ...string, keyName: string): Promise`: Deletes a project secret. Example: ```...

(UNLIKELY_OPENING_PUNCTUATION)

src/lib/platformApi.ts (4)

116-128: Optional input validation suggestion for platformLogin.
Consider ensuring email and password are non-empty strings before making the API call, similar to the validation you perform in other functions like inviteDeveloper.


269-283: Consider handling edge cases with Base64 validation.
This utility rejects certain valid forms of Base64 (like URL-safe variants). If your use cases require broader support, consider relaxing or extending the pattern.


370-386: Consider adding stricter email format validation.
While checking for empty emails is good, you might also validate basic structure (e.g., presence of “@”) to catch typos or malformed addresses.


426-436: Use of an enum for user roles could reduce errors.
Managing roles as raw strings increases the risk of typos and inconsistencies. An enum or constant set ensures safer updates and better maintainability.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a9edb77 and c64c2f5.

📒 Files selected for processing (8)
  • docs/PLATFORM.md (1 hunks)
  • src/lib/api.ts (2 hunks)
  • src/lib/attestation.ts (1 hunks)
  • src/lib/developer.tsx (1 hunks)
  • src/lib/encryptedApi.ts (4 hunks)
  • src/lib/platformApi.ts (1 hunks)
  • src/lib/test/integration/developer.test.ts (1 hunks)
  • src/lib/util.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/lib/attestation.ts
  • src/lib/api.ts
  • src/lib/util.ts
🧰 Additional context used
🧠 Learnings (2)
src/lib/developer.tsx (1)
Learnt from: AnthonyRonning
PR: OpenSecretCloud/OpenSecret-SDK#24
File: src/lib/developer.tsx:469-489
Timestamp: 2025-02-28T02:11:53.459Z
Learning: Storing tokens securely (using httpOnly cookies or other secure storage methods instead of localStorage) is planned for a future update of the OpenSecret-SDK.
src/lib/platformApi.ts (1)
Learnt from: AnthonyRonning
PR: OpenSecretCloud/OpenSecret-SDK#24
File: src/lib/platformApi.ts:291-300
Timestamp: 2025-02-28T02:12:34.704Z
Learning: The listProjectSecrets function in platformApi.ts only returns metadata about secrets (key_name and timestamps) and not the actual secret values, following security best practices.
🪛 GitHub Check: test
src/lib/test/integration/developer.test.ts

[failure] 12-12: error: Test developer credentials must be set in .env.local

  at /home/runner/work/OpenSecret-SDK/OpenSecret-SDK/src/lib/test/integration/developer.test.ts:12:9
🪛 ESLint
src/lib/test/integration/developer.test.ts

[error] 41-41: 'loginError' is defined but never used.

(@typescript-eslint/no-unused-vars)


[error] 59-59: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 100-100: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 143-143: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 147-147: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 157-157: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 169-169: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 190-190: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 201-201: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 210-210: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 219-219: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 258-258: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 275-275: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 284-284: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 287-287: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 304-304: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 309-309: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 340-340: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 347-347: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 387-387: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 415-415: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 430-430: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 438-438: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 446-446: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 449-449: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 472-472: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 476-476: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 519-519: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 563-563: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 568-568: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 589-589: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 595-595: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 646-646: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 654-654: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 661-661: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 748-748: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 770-770: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 779-779: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 787-787: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 794-794: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 822-822: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 832-832: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 840-840: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 850-850: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 872-872: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 880-880: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 893-893: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 900-900: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 931-931: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 939-939: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 992-992: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1017-1017: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1025-1025: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1035-1035: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1043-1043: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1054-1054: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1087-1087: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1098-1098: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1156-1156: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1165-1165: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1190-1190: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1200-1200: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1284-1284: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1316-1316: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1329-1329: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1343-1343: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1356-1356: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1369-1369: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1380-1380: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1428-1428: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1451-1451: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1529-1529: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1545-1545: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1589-1589: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1608-1608: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1643-1643: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1656-1656: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1668-1668: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1684-1684: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1775-1775: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1815-1815: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1893-1893: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1915-1915: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1923-1923: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1935-1935: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1943-1943: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1950-1950: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1981-1981: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1989-1989: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1997-1997: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 2008-2008: 'error' is defined but never used.

(@typescript-eslint/no-unused-vars)


[error] 2012-2012: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)

🪛 GitHub Actions: Library Tests
src/lib/test/integration/developer.test.ts

[error] 1-1: Unhandled error between tests

🪛 LanguageTool
docs/PLATFORM.md

[uncategorized] ~221-~221: Loose punctuation mark.
Context: ...... } ``` ### Developer State - auth: An object containing the current develo...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~232-~232: Loose punctuation mark.
Context: ...string): Promise`: Signs in a developer with the provided ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~233-~233: Loose punctuation mark.
Context: ...string): Promise`: Registers a new developer account with ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~234-~234: Loose punctuation mark.
Context: ...ly updated. - signOut(): Promise<void>: Signs out the current developer by remo...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~235-~235: Loose punctuation mark.
Context: ...l. - refetchDeveloper(): Promise<void>: Refreshes the developer's authenticatio...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~239-~239: Loose punctuation mark.
Context: ... Attestation Verification - pcrConfig: An object containing additional PCR0 ha...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~240-~240: Loose punctuation mark.
Context: ... to validate against. - getAttestation: Gets attestation from the enclave. - `a...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~241-~241: Loose punctuation mark.
Context: ...ation from the enclave. - authenticate: Authenticates an attestation document. ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~242-~242: Loose punctuation mark.
Context: ...on document. - parseAttestationForView: Parses an attestation document for view...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~243-~243: Loose punctuation mark.
Context: ...document for viewing. - awsRootCertDer: AWS root certificate in DER format. - `...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~244-~244: Loose punctuation mark.
Context: ... in DER format. - expectedRootCertHash: Expected hash of the AWS root certifica...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~245-~245: Loose punctuation mark.
Context: ...ertificate. - getAttestationDocument(): Gets and verifies an attestation docume...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~269-~269: Loose punctuation mark.
Context: ...on(name: string): Promise`: Creates a new organization with the giv...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~270-~270: Loose punctuation mark.
Context: ...rganizations(): Promise<Organization[]>`: Lists all organizations the developer h...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~271-~271: Loose punctuation mark.
Context: ...anization(orgId: string): Promise`: Deletes an organization (requires owner...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~302-~302: Loose punctuation mark.
Context: ...description?: string): Promise`: Creates a new project within an organiz...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~303-~303: Loose punctuation mark.
Context: ...ects(orgId: string): Promise<Project[]>`: Lists all projects within an organizati...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~304-~304: Loose punctuation mark.
Context: ...g, projectId: string): Promise: Gets a single project by ID. - updateP...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~305-~305: Loose punctuation mark.
Context: ...g; status?: string }): Promise: Updates project details. - deleteProje...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~306-~306: Loose punctuation mark.
Context: ...ring, projectId: string): Promise`: Deletes a project. Example: ```tsx con...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~348-~348: Loose punctuation mark.
Context: ...secret: string): Promise`: Creates a new secret for a project. The...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~349-~349: Loose punctuation mark.
Context: ...ctId: string): Promise<ProjectSecret[]>: Lists all secrets for a project. - del...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~350-~350: Loose punctuation mark.
Context: ...string, keyName: string): Promise`: Deletes a project secret. Example: ```...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~389-~389: Loose punctuation mark.
Context: ...jectId: string): Promise`: Gets email configuration for a project....

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~390-~390: Loose punctuation mark.
Context: ... EmailSettings): Promise`: Updates email configuration. Example: ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~428-~428: Loose punctuation mark.
Context: ...jectId: string): Promise: Gets OAuth settings for a project. - u...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~429-~429: Loose punctuation mark.
Context: ... OAuthSettings): Promise`: Updates OAuth configuration. Example: ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~475-~475: Loose punctuation mark.
Context: ...?: string): Promise`: Creates an invitation to join an organi...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~476-~476: Loose punctuation mark.
Context: ... string): Promise<OrganizationMember[]>`: Lists all members of an organization. -...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~477-~477: Loose punctuation mark.
Context: ... string): Promise<OrganizationInvite[]>`: Lists all pending invitations for an or...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~478-~478: Loose punctuation mark.
Context: ...e: string): Promise`: Gets a specific invitation by UUID code...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~479-~479: Loose punctuation mark.
Context: ...: string): Promise<{ message: string }>: Deletes an invitation. - updateMemberR...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~480-~480: Loose punctuation mark.
Context: ...e: string): Promise: Updates a member's role. - removeMembe...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~481-~481: Loose punctuation mark.
Context: ... string, userId: string): Promise`: Removes a member from the organization....

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~482-~482: Loose punctuation mark.
Context: ...: string): Promise<{ message: string }>`: Accepts an organization invitation. Ex...

(UNLIKELY_OPENING_PUNCTUATION)

🔇 Additional comments (9)
src/lib/developer.tsx (3)

496-497: Avoid storing tokens in localStorage for security.

Storing access and refresh tokens in localStorage is susceptible to XSS attacks. Based on the retrieved learning, more secure token storage is planned for a future update.


15-25: Well-structured type imports for platform API.

Good job organizing the type imports from platformApi. This helps maintain a clean separation of concerns and makes the code more maintainable.


416-424: Well-designed component props with appropriate defaults.

The OpenSecretDeveloper component has clear props with appropriate types and defaults. The optional pcrConfig with a default empty object is a good pattern.

docs/PLATFORM.md (2)

9-22: Excellent component example with clear initialization.

The documentation provides a clear example of how to initialize the OpenSecretDeveloper component with the required apiUrl parameter and optional pcrConfig.


546-667: Comprehensive example demonstrating the API.

The complete example demonstrates a practical implementation of the Developer Platform API, including organization and project management. It's well-structured and clearly illustrates the usage patterns.

src/lib/platformApi.ts (4)

1-2: No issues with import statements.
The imports from encryptedApi and authenticatedApi appear straightforward.


172-193: Storing tokens in localStorage is potentially risky.
This mirrors a flagged in a past review. Attacks exploiting XSS can expose tokens if they are in localStorage. Consider secure alternatives such as HTTP-only cookies.


285-303: Great job enforcing base64-encoded secrets.
Validating and refusing plain-text secrets helps maintain strong security. Implementation looks sound.


305-314: Commendable approach to protect secret values.
Returning only metadata for secrets prevents accidental leakage of secret content. This aligns with best practices mentioned in your previous learnings.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (4)
src/lib/apiConfig.ts (2)

44-46: Consider a more robust path detection mechanism.

The current implementation relies on checking if the path includes "/platform/", which could be fragile if URL structures change in the future.

-  isPlatformPath(path: string): boolean {
-    return path.includes("/platform/");
+  isPlatformPath(path: string): boolean {
+    // More specific pattern matching
+    return /^\/platform\/|\/api\/platform\//.test(path);

63-71: Consider additional URL path validation.

The buildUrl method doesn't handle potential edge cases like paths that might not start with a slash.

  buildUrl(path: string): string {
    // If the path is already a full URL, return it unchanged
    if (path.startsWith("http")) {
      return path;
    }

    const endpoint = this.resolveEndpoint(path);
-    return `${endpoint.baseUrl}${path}`;
+    // Ensure path starts with a slash and handle potential double slash
+    const normalizedPath = path.startsWith('/') ? path : `/${path}`;
+    const baseUrl = endpoint.baseUrl.endsWith('/') 
+      ? endpoint.baseUrl.slice(0, -1) 
+      : endpoint.baseUrl;
+    return `${baseUrl}${normalizedPath}`;
  }
src/lib/developer.tsx (2)

474-489: Consider error handling enhancement for getAttestationDocument.

The error handling in getAttestationDocument could be more specific to help with debugging.

const getAttestationDocument = async () => {
  const nonce = window.crypto.randomUUID();
-  const response = await fetch(`${apiUrl}/attestation/${nonce}`);
-  if (!response.ok) {
-    throw new Error("Failed to fetch attestation document");
+  try {
+    const response = await fetch(`${apiUrl}/attestation/${nonce}`);
+    if (!response.ok) {
+      throw new Error(`Failed to fetch attestation document: ${response.status} ${response.statusText}`);
+    }
+
+    const data = await response.json();
+    const verifiedDocument = await authenticate(
+      data.attestation_document,
+      AWS_ROOT_CERT_DER,
+      nonce
+    );
+    return parseAttestationForView(verifiedDocument, verifiedDocument.cabundle, pcrConfig);
+  } catch (error) {
+    console.error("Attestation document error:", error);
+    throw error;
   }
-
-  const data = await response.json();
-  const verifiedDocument = await authenticate(
-    data.attestation_document,
-    AWS_ROOT_CERT_DER,
-    nonce
-  );
-  return parseAttestationForView(verifiedDocument, verifiedDocument.cabundle, pcrConfig);
};

530-545: Improve signOut implementation with proper localStorage access check.

Similar to fetchDeveloper, the signOut function should also check if window is defined before accessing localStorage.

signOut: async () => {
+  if (typeof window === 'undefined') {
+    setAuth({
+      loading: false,
+      developer: undefined
+    });
+    return;
+  }
+
  const refresh_token = window.localStorage.getItem("refresh_token");
  if (refresh_token) {
    try {
      await platformApi.platformLogout(refresh_token);
    } catch (error) {
      console.error("Error during logout:", error);
    }
  }
  localStorage.removeItem("access_token");
  localStorage.removeItem("refresh_token");
  setAuth({
    loading: false,
    developer: undefined
  });
},
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c64c2f5 and 71e7b23.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (7)
  • package.json (3 hunks)
  • src/lib/apiConfig.ts (1 hunks)
  • src/lib/developer.tsx (1 hunks)
  • src/lib/encryptedApi.ts (4 hunks)
  • src/lib/index.ts (1 hunks)
  • src/lib/main.tsx (1 hunks)
  • src/lib/util.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/lib/util.ts
🧰 Additional context used
🧠 Learnings (1)
src/lib/developer.tsx (1)
Learnt from: AnthonyRonning
PR: OpenSecretCloud/OpenSecret-SDK#24
File: src/lib/developer.tsx:469-489
Timestamp: 2025-02-28T02:11:53.459Z
Learning: Storing tokens securely (using httpOnly cookies or other secure storage methods instead of localStorage) is planned for a future update of the OpenSecret-SDK.
🔇 Additional comments (21)
src/lib/main.tsx (1)

447-453: Clean implementation of dynamic API configuration.

The dynamic import approach for apiConfig is a good solution to avoid circular dependencies. The code correctly configures both the app and platform API URLs after component initialization.

package.json (3)

3-3: Version bump to 1.0.0-beta.1 indicates a significant update.

This version change follows semantic versioning principles and aligns with the introduction of the new Developer Platform API functionality.


27-28: Enhanced React compatibility.

Broadening React peer dependencies to support both v18 and v19 improves library compatibility with different React applications.


44-45: Updated React type definitions.

The React type definitions have been updated to v19, which aligns with the peer dependency changes.

src/lib/index.ts (4)

10-11: New API configuration exports.

Good addition of the apiConfig exports, providing access to the API configuration service for consumers of the library.


15-15: Developer context exports added.

Properly exports the new developer context components, making them available to library consumers.


17-19: Hook exports expanded.

Comment correctly updated to reflect multiple hooks, and useOpenSecretDeveloper hook is properly exported.


23-30: Developer types exports.

Good addition of type exports for the developer platform, which will help consumers understand and use the API correctly.

src/lib/apiConfig.ts (3)

5-10: Well-defined types for API configuration.

Clear and concise type definitions for ApiContext and ApiEndpoint that establish the foundational structure for the API configuration service.


15-39: Clean implementation of the configuration service.

The ApiConfigService class provides a good encapsulation of API URL management with appropriate getters and a configuration method.


81-82: Singleton instance appropriately exported.

Using a singleton pattern is a good choice for this type of service, as it ensures consistent configuration across the application.

src/lib/encryptedApi.ts (5)

4-5: New imports enable platform API integration.

These imports add support for platform API token refreshing and configuration, which are needed for the enhanced API call handling in this file.


27-37: Good implementation of dynamic token refresh based on URL context.

The code now intelligently determines which refresh function to use based on the API context, allowing for different authentication flows between the regular API and platform API.


55-55: Enhanced error logging with URL context.

Adding the URL to the 401 error log is a good improvement that will make debugging authentication issues much easier.


87-90: Well-structured API endpoint resolution.

The implementation properly uses the apiConfig to determine whether the call is for the platform API and sets the appropriate endpoint URL accordingly.


91-91: Attestation now correctly handles platform API context.

The getAttestation calls now include the explicit API URL parameter when needed, ensuring attestations are correctly fetched from the right enclave endpoint.

Also applies to: 95-95

src/lib/developer.tsx (5)

1-26: Well-organized imports and type definitions.

The imports are logically structured, importing necessary React hooks, attestation utilities, and platform API types.


27-345: Comprehensive and well-documented API surface.

The type definitions and JSDoc comments provide excellent documentation for developers using this context. The structure is clear and the descriptions are thorough.


416-444: Good API URL validation and configuration.

The component properly validates the API URL parameter and sets it up for platform API calls. The dynamic import of apiConfig avoids circular dependency issues.


446-455: Check for window before accessing localStorage.

The code directly accesses window.localStorage without first checking if window is defined, which could cause issues in server-side rendering (SSR) environments.

async function fetchDeveloper() {
+  if (typeof window === 'undefined') {
+    setAuth({
+      loading: false,
+      developer: undefined
+    });
+    return;
+  }
+
  const access_token = window.localStorage.getItem("access_token");
  const refresh_token = window.localStorage.getItem("refresh_token");
  if (!access_token || !refresh_token) {
    setAuth({
      loading: false,
      developer: undefined
    });
    return;
  }

498-499: Storing tokens in localStorage.

I see from the retrieved learnings that storing tokens securely (using httpOnly cookies or other secure storage methods) is planned for a future update of the OpenSecret-SDK.

Also applies to: 515-517, 539-540

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
src/lib/test/integration/developer.test.ts (1)

41-41: Remove or utilize unused error variable
The variable loginError is defined but never used in this catch block. Consider using it in the log statement for clarity (console.warn("Login failed", loginError)) or removing it entirely.

🧰 Tools
🪛 ESLint

[error] 41-41: 'loginError' is defined but never used.

(@typescript-eslint/no-unused-vars)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 71e7b23 and 25e5a99.

📒 Files selected for processing (5)
  • docs/PLATFORM.md (1 hunks)
  • src/lib/developer.tsx (1 hunks)
  • src/lib/main.tsx (1 hunks)
  • src/lib/platformApi.ts (1 hunks)
  • src/lib/test/integration/developer.test.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/lib/main.tsx
🧰 Additional context used
🧠 Learnings (2)
src/lib/developer.tsx (1)
Learnt from: AnthonyRonning
PR: OpenSecretCloud/OpenSecret-SDK#24
File: src/lib/developer.tsx:469-489
Timestamp: 2025-02-28T02:11:53.459Z
Learning: Storing tokens securely (using httpOnly cookies or other secure storage methods instead of localStorage) is planned for a future update of the OpenSecret-SDK.
src/lib/platformApi.ts (1)
Learnt from: AnthonyRonning
PR: OpenSecretCloud/OpenSecret-SDK#24
File: src/lib/platformApi.ts:291-300
Timestamp: 2025-02-28T02:12:34.704Z
Learning: The listProjectSecrets function in platformApi.ts only returns metadata about secrets (key_name and timestamps) and not the actual secret values, following security best practices.
🪛 LanguageTool
docs/PLATFORM.md

[uncategorized] ~247-~247: Loose punctuation mark.
Context: ...... } ``` ### Developer State - auth: An object containing the current develo...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~258-~258: Loose punctuation mark.
Context: ...string): Promise`: Signs in a developer with the provided ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~259-~259: Loose punctuation mark.
Context: ...string): Promise`: Registers a new developer account with ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~260-~260: Loose punctuation mark.
Context: ...ly updated. - signOut(): Promise<void>: Signs out the current developer by remo...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~261-~261: Loose punctuation mark.
Context: ...l. - refetchDeveloper(): Promise<void>: Refreshes the developer's authenticatio...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~262-~262: Loose punctuation mark.
Context: ...erifyEmail(code: string): Promise`: Verifies a developer's email address us...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~263-~263: Loose punctuation mark.
Context: ...ionCode(): Promise<{ message: string }>`: Requests a new verification email to be...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~264-~264: Loose punctuation mark.
Context: ...onEmail(): Promise<{ message: string }>: Alias for requestNewVerificationCode()...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~268-~268: Loose punctuation mark.
Context: ... Attestation Verification - pcrConfig: An object containing additional PCR0 ha...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~269-~269: Loose punctuation mark.
Context: ... to validate against. - getAttestation: Gets attestation from the enclave. - `a...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~270-~270: Loose punctuation mark.
Context: ...ation from the enclave. - authenticate: Authenticates an attestation document. ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~271-~271: Loose punctuation mark.
Context: ...on document. - parseAttestationForView: Parses an attestation document for view...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~272-~272: Loose punctuation mark.
Context: ...document for viewing. - awsRootCertDer: AWS root certificate in DER format. - `...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~273-~273: Loose punctuation mark.
Context: ... in DER format. - expectedRootCertHash: Expected hash of the AWS root certifica...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~274-~274: Loose punctuation mark.
Context: ...ertificate. - getAttestationDocument(): Gets and verifies an attestation docume...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~298-~298: Loose punctuation mark.
Context: ...on(name: string): Promise`: Creates a new organization with the giv...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~299-~299: Loose punctuation mark.
Context: ...rganizations(): Promise<Organization[]>`: Lists all organizations the developer h...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~300-~300: Loose punctuation mark.
Context: ...anization(orgId: string): Promise`: Deletes an organization (requires owner...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~331-~331: Loose punctuation mark.
Context: ...description?: string): Promise`: Creates a new project within an organiz...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~332-~332: Loose punctuation mark.
Context: ...ects(orgId: string): Promise<Project[]>`: Lists all projects within an organizati...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~333-~333: Loose punctuation mark.
Context: ...g, projectId: string): Promise: Gets a single project by ID. - updateP...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~334-~334: Loose punctuation mark.
Context: ...g; status?: string }): Promise: Updates project details. - deleteProje...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~335-~335: Loose punctuation mark.
Context: ...ring, projectId: string): Promise`: Deletes a project. Example: ```tsx con...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~377-~377: Loose punctuation mark.
Context: ...secret: string): Promise`: Creates a new secret for a project. The...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~378-~378: Loose punctuation mark.
Context: ...ctId: string): Promise<ProjectSecret[]>: Lists all secrets for a project. - del...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~379-~379: Loose punctuation mark.
Context: ...string, keyName: string): Promise`: Deletes a project secret. Example: ```...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~418-~418: Loose punctuation mark.
Context: ...jectId: string): Promise`: Gets email configuration for a project....

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~419-~419: Loose punctuation mark.
Context: ... EmailSettings): Promise`: Updates email configuration. Example: ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~457-~457: Loose punctuation mark.
Context: ...jectId: string): Promise: Gets OAuth settings for a project. - u...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~458-~458: Loose punctuation mark.
Context: ... OAuthSettings): Promise`: Updates OAuth configuration. Example: ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~504-~504: Loose punctuation mark.
Context: ...?: string): Promise`: Creates an invitation to join an organi...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~505-~505: Loose punctuation mark.
Context: ... string): Promise<OrganizationMember[]>`: Lists all members of an organization. -...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~506-~506: Loose punctuation mark.
Context: ... string): Promise<OrganizationInvite[]>`: Lists all pending invitations for an or...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~507-~507: Loose punctuation mark.
Context: ...e: string): Promise`: Gets a specific invitation by UUID code...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~508-~508: Loose punctuation mark.
Context: ...: string): Promise<{ message: string }>: Deletes an invitation. - updateMemberR...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~509-~509: Loose punctuation mark.
Context: ...e: string): Promise: Updates a member's role. - removeMembe...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~510-~510: Loose punctuation mark.
Context: ... string, userId: string): Promise`: Removes a member from the organization....

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~511-~511: Loose punctuation mark.
Context: ...: string): Promise<{ message: string }>`: Accepts an organization invitation. Ex...

(UNLIKELY_OPENING_PUNCTUATION)

🪛 GitHub Check: test
src/lib/test/integration/developer.test.ts

[failure] 12-12: error: Test developer credentials must be set in .env.local

  at /home/runner/work/OpenSecret-SDK/OpenSecret-SDK/src/lib/test/integration/developer.test.ts:12:9
🪛 ESLint
src/lib/test/integration/developer.test.ts

[error] 41-41: 'loginError' is defined but never used.

(@typescript-eslint/no-unused-vars)


[error] 59-59: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 100-100: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 143-143: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 147-147: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 157-157: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 169-169: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 190-190: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 201-201: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 210-210: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 219-219: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 258-258: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 275-275: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 284-284: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 287-287: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 304-304: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 309-309: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 340-340: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 347-347: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 387-387: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 415-415: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 430-430: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 438-438: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 446-446: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 449-449: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 472-472: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 476-476: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 519-519: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 563-563: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 568-568: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 589-589: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 595-595: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 646-646: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 654-654: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 661-661: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 748-748: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 770-770: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 779-779: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 787-787: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 794-794: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 822-822: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 832-832: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 840-840: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 850-850: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 872-872: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 880-880: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 893-893: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 900-900: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 931-931: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 939-939: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 992-992: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1017-1017: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1025-1025: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1035-1035: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1043-1043: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1054-1054: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1087-1087: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1098-1098: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1156-1156: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1165-1165: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1190-1190: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1200-1200: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1222-1222: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1238-1238: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1250-1250: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1270-1270: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1276-1276: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1360-1360: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1392-1392: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1405-1405: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1419-1419: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1432-1432: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1445-1445: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1456-1456: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1504-1504: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1527-1527: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1605-1605: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1621-1621: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1665-1665: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1684-1684: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1719-1719: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1732-1732: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1744-1744: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1760-1760: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1851-1851: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1891-1891: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1969-1969: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1991-1991: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1999-1999: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 2011-2011: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 2019-2019: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 2026-2026: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 2057-2057: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 2065-2065: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 2073-2073: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 2084-2084: 'error' is defined but never used.

(@typescript-eslint/no-unused-vars)


[error] 2088-2088: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)

🔇 Additional comments (8)
src/lib/test/integration/developer.test.ts (3)

11-13: Ensure environment variables are set for integration tests
This test will fail if the required environment variables (TEST_DEVELOPER_EMAIL, TEST_DEVELOPER_PASSWORD, TEST_DEVELOPER_NAME) are not provided in .env.local. Make sure to set them before running these tests.

🧰 Tools
🪛 GitHub Check: test

[failure] 12-12: error: Test developer credentials must be set in .env.local

  at /home/runner/work/OpenSecret-SDK/OpenSecret-SDK/src/lib/test/integration/developer.test.ts:12:9

59-59: Use 'unknown' instead of 'any' for error parameters
This was flagged in an earlier review. Replacing any with unknown or a more specific type for error parameters preserves type safety and clarifies expectations.

-} catch (error: any) {
+} catch (error: unknown) {
   console.error("Error:", error);
}

Also applies to: 100-100, 143-143, 147-147, 157-157, 169-169, 190-190, 201-201, 210-210, 219-219, 258-258, 275-275, 284-284, 287-287, 304-304, 309-309, 340-340, 347-347, 387-387, 415-415, 430-430, 438-438, 446-446, 449-449, 472-472, 476-476, 519-519, 563-563, 568-568, 589-589, 595-595, 646-646, 654-654, 661-661, 706-706, 715-715, 723-723, 730-730, 758-758, 768-768, 776-776, 786-786, 808-808, 816-816, 829-829, 836-836, 867-867, 875-875, 928-928, 953-953, 961-961, 971-971, 979-979, 990-990, 1023-1023, 1034-1034, 1092-1092, 1101-1101, 1126-1126, 1136-1136, 1220-1220, 1252-1252, 1265-1265, 1279-1279, 1292-1292, 1305-1305, 1316-1316, 1364-1364, 1387-1387, 1465-1465, 1481-1481, 1525-1525, 1544-1544, 1579-1579, 1592-1592, 1604-1604, 1620-1620, 1711-1711, 1751-1751

🧰 Tools
🪛 ESLint

[error] 59-59: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


37-38: Storing tokens in localStorage is risky
Persisting access_token and refresh_token in window.localStorage exposes them to potential XSS attacks. A previous review noted that you plan to transition to more secure storage. Consider HTTP-only cookies or other secure approaches.

Also applies to: 54-55, 94-95, 114-115, 179-180

src/lib/developer.tsx (2)

479-489: Check for window before accessing localStorage
When running in SSR or non-browser environments, window may be undefined. A prior review suggested conditionally checking for window before using localStorage.


531-532: Revisit localStorage usage for token storage
Storing tokens in localStorage can leave you vulnerable to XSS. Previous review comments indicate this will be addressed later. Until then, ensure any potential XSS vectors are hardened.

Also applies to: 548-549, 564-564, 572-572

docs/PLATFORM.md (1)

247-247: Ignore minor punctuation warnings
The static analysis tool flagged punctuation usage in headings and code comments (e.g., "Promise`:"). These are stylistic warnings with minimal impact.

Also applies to: 258-258, 259-259, 260-260, 261-261, 262-262, 263-263, 264-264, 268-268, 269-269, 270-270, 271-271, 272-272, 273-273, 274-274, 298-298, 299-299, 300-300, 331-331, 332-332, 333-333, 334-334, 335-335, 377-377, 378-378, 379-379, 418-418, 419-419, 457-457, 458-458, 504-504, 505-505, 506-506, 507-507, 508-508, 509-509, 510-510, 511-511

🧰 Tools
🪛 LanguageTool

[uncategorized] ~247-~247: Loose punctuation mark.
Context: ...... } ``` ### Developer State - auth: An object containing the current develo...

(UNLIKELY_OPENING_PUNCTUATION)

src/lib/platformApi.ts (2)

172-173: Reevaluate localStorage usage when refreshing tokens
Using window.localStorage for credential storage makes tokens accessible to scripts on the page. If an attacker injects code, they could steal credentials. Consider secure cookies or another secure storage method.

Also applies to: 186-187


305-314: Secure design: secrets listing returns only metadata
It's good that listProjectSecrets omits the secret values themselves, reducing the risk of accidental exposure in logs or front-end code. This adheres to best practices for secret handling.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (6)
src/lib/test/integration/developer.test.ts (1)

528-537: Consider adding window check for server-side rendering

The code directly accesses window.localStorage without checking if window is defined first, which could cause issues in server-side rendering environments.

async function fetchDeveloper() {
+  if (typeof window === 'undefined') {
+    setAuth({
+      loading: false,
+      developer: undefined
+    });
+    return;
+  }
+
  const access_token = window.localStorage.getItem("access_token");
  const refresh_token = window.localStorage.getItem("refresh_token");
  if (!access_token || !refresh_token) {
    setAuth({
      loading: false,
      developer: undefined
    });
    return;
  }
src/lib/developer.tsx (2)

528-537: Add window check for server-side rendering environments

The code directly accesses window.localStorage without checking if window is defined first, which could cause issues in server-side rendering environments.

async function fetchDeveloper() {
+  if (typeof window === 'undefined') {
+    setAuth({
+      loading: false,
+      developer: undefined
+    });
+    return;
+  }
+
  const access_token = window.localStorage.getItem("access_token");
  const refresh_token = window.localStorage.getItem("refresh_token");
  if (!access_token || !refresh_token) {

612-627: Consider consistent localStorage access pattern

In the signOut method, there's an inconsistency where some methods use window.localStorage while others use localStorage directly. Standardize on one approach.

signOut: async () => {
-      const refresh_token = window.localStorage.getItem("refresh_token");
+      if (typeof window === 'undefined') {
+        return;
+      }
+      
+      const refresh_token = window.localStorage.getItem("refresh_token");
      if (refresh_token) {
        try {
          await platformApi.platformLogout(refresh_token);
        } catch (error) {
          console.error("Error during logout:", error);
        }
      }
-      localStorage.removeItem("access_token");
-      localStorage.removeItem("refresh_token");
+      window.localStorage.removeItem("access_token");
+      window.localStorage.removeItem("refresh_token");
      setAuth({
        loading: false,
        developer: undefined
      });
    },
src/lib/platformApi.ts (3)

106-115: Consider multi-endpoint scenarios.
setPlatformApiUrl() and getPlatformApiUrl() rely on a single static variable, which may not scale if multiple endpoints need to be hit concurrently. If you plan to support multiple base URLs, consider a more robust configuration approach.


116-156: Clear authentication methods.
platformLogin, platformRegister, and platformLogout are straightforward, but note that platformLogout does not remove any stored tokens (e.g., in local storage). Consider explicitly clearing tokens on logout to reduce security risks.

 export async function platformLogout(refresh_token: string): Promise<void> {
   ...
 }
 
+// Example snippet to remove tokens locally:
+window.localStorage.removeItem("access_token");
+window.localStorage.removeItem("refresh_token");

269-284: Verify actual decodability for stronger validation.
isValidBase64() checks length and character set, which is often enough. However, if you need absolute certainty, you could decode the string in a try-catch block to confirm it’s valid Base64.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c7f08ad and 80c198a.

📒 Files selected for processing (5)
  • docs/PLATFORM.md (1 hunks)
  • package.json (3 hunks)
  • src/lib/developer.tsx (1 hunks)
  • src/lib/platformApi.ts (1 hunks)
  • src/lib/test/integration/developer.test.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (2)
src/lib/developer.tsx (1)
Learnt from: AnthonyRonning
PR: OpenSecretCloud/OpenSecret-SDK#24
File: src/lib/developer.tsx:469-489
Timestamp: 2025-02-28T02:11:53.459Z
Learning: Storing tokens securely (using httpOnly cookies or other secure storage methods instead of localStorage) is planned for a future update of the OpenSecret-SDK.
src/lib/platformApi.ts (1)
Learnt from: AnthonyRonning
PR: OpenSecretCloud/OpenSecret-SDK#24
File: src/lib/platformApi.ts:291-300
Timestamp: 2025-02-28T02:12:34.704Z
Learning: The listProjectSecrets function in platformApi.ts only returns metadata about secrets (key_name and timestamps) and not the actual secret values, following security best practices.
🪛 LanguageTool
docs/PLATFORM.md

[uncategorized] ~327-~327: Loose punctuation mark.
Context: ...... } ``` ### Developer State - auth: An object containing the current develo...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~338-~338: Loose punctuation mark.
Context: ...string): Promise`: Signs in a developer with the provided ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~339-~339: Loose punctuation mark.
Context: ...string): Promise`: Registers a new developer account with ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~340-~340: Loose punctuation mark.
Context: ...ly updated. - signOut(): Promise<void>: Signs out the current developer by remo...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~341-~341: Loose punctuation mark.
Context: ...l. - refetchDeveloper(): Promise<void>: Refreshes the developer's authenticatio...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~342-~342: Loose punctuation mark.
Context: ...erifyEmail(code: string): Promise`: Verifies a developer's email address us...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~343-~343: Loose punctuation mark.
Context: ...ionCode(): Promise<{ message: string }>`: Requests a new verification email to be...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~344-~344: Loose punctuation mark.
Context: ...onEmail(): Promise<{ message: string }>: Alias for requestNewVerificationCode()...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~345-~345: Loose punctuation mark.
Context: ...g, hashedSecret: string): Promise`: Initiates the password reset process fo...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~346-~346: Loose punctuation mark.
Context: ...: string): Promise<{ message: string }>`: Completes the password reset process fo...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~347-~347: Loose punctuation mark.
Context: ...: string): Promise<{ message: string }>`: Changes the password for an authenticat...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~351-~351: Loose punctuation mark.
Context: ... Attestation Verification - pcrConfig: An object containing additional PCR0 ha...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~352-~352: Loose punctuation mark.
Context: ... to validate against. - getAttestation: Gets attestation from the enclave. - `a...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~353-~353: Loose punctuation mark.
Context: ...ation from the enclave. - authenticate: Authenticates an attestation document. ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~354-~354: Loose punctuation mark.
Context: ...on document. - parseAttestationForView: Parses an attestation document for view...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~355-~355: Loose punctuation mark.
Context: ...document for viewing. - awsRootCertDer: AWS root certificate in DER format. - `...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~356-~356: Loose punctuation mark.
Context: ... in DER format. - expectedRootCertHash: Expected hash of the AWS root certifica...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~357-~357: Loose punctuation mark.
Context: ...ertificate. - getAttestationDocument(): Gets and verifies an attestation docume...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~381-~381: Loose punctuation mark.
Context: ...on(name: string): Promise`: Creates a new organization with the giv...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~382-~382: Loose punctuation mark.
Context: ...rganizations(): Promise<Organization[]>`: Lists all organizations the developer h...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~383-~383: Loose punctuation mark.
Context: ...anization(orgId: string): Promise`: Deletes an organization (requires owner...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~414-~414: Loose punctuation mark.
Context: ...description?: string): Promise`: Creates a new project within an organiz...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~415-~415: Loose punctuation mark.
Context: ...ects(orgId: string): Promise<Project[]>`: Lists all projects within an organizati...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~416-~416: Loose punctuation mark.
Context: ...g, projectId: string): Promise: Gets a single project by ID. - updateP...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~417-~417: Loose punctuation mark.
Context: ...g; status?: string }): Promise: Updates project details. - deleteProje...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~418-~418: Loose punctuation mark.
Context: ...ring, projectId: string): Promise`: Deletes a project. Example: ```tsx con...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~458-~458: It seems likely that a singular genitive (’s) apostrophe is missing.
Context: ...updated_at: string; }; ``` ### Project Secrets API Methods - `createProjectSecret(org...

(AI_HYDRA_LEO_APOSTROPHE_S_XS)


[uncategorized] ~460-~460: Loose punctuation mark.
Context: ...secret: string): Promise`: Creates a new secret for a project. The...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~461-~461: Loose punctuation mark.
Context: ...ctId: string): Promise<ProjectSecret[]>: Lists all secrets for a project. - del...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~462-~462: Loose punctuation mark.
Context: ...string, keyName: string): Promise`: Deletes a project secret. Example: ```...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~501-~501: Loose punctuation mark.
Context: ...jectId: string): Promise`: Gets email configuration for a project....

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~502-~502: Loose punctuation mark.
Context: ... EmailSettings): Promise`: Updates email configuration. Example: ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~540-~540: Loose punctuation mark.
Context: ...jectId: string): Promise: Gets OAuth settings for a project. - u...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~541-~541: Loose punctuation mark.
Context: ... OAuthSettings): Promise`: Updates OAuth configuration. Example: ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~587-~587: Loose punctuation mark.
Context: ...?: string): Promise`: Creates an invitation to join an organi...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~588-~588: Loose punctuation mark.
Context: ... string): Promise<OrganizationMember[]>`: Lists all members of an organization. -...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~589-~589: Loose punctuation mark.
Context: ... string): Promise<OrganizationInvite[]>`: Lists all pending invitations for an or...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~590-~590: Loose punctuation mark.
Context: ...e: string): Promise`: Gets a specific invitation by UUID code...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~591-~591: Loose punctuation mark.
Context: ...: string): Promise<{ message: string }>: Deletes an invitation. - updateMemberR...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~592-~592: Loose punctuation mark.
Context: ...e: string): Promise: Updates a member's role. - removeMembe...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~593-~593: Loose punctuation mark.
Context: ... string, userId: string): Promise`: Removes a member from the organization....

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~594-~594: Loose punctuation mark.
Context: ...: string): Promise<{ message: string }>`: Accepts an organization invitation. Ex...

(UNLIKELY_OPENING_PUNCTUATION)

🪛 ESLint
src/lib/test/integration/developer.test.ts

[error] 41-41: 'loginError' is defined but never used.

(@typescript-eslint/no-unused-vars)


[error] 59-59: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 100-100: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 143-143: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 147-147: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 157-157: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 169-169: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 190-190: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 201-201: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 210-210: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 219-219: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 258-258: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 275-275: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 284-284: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 287-287: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 304-304: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 309-309: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 340-340: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 347-347: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 387-387: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 415-415: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 430-430: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 438-438: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 446-446: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 449-449: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 472-472: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 476-476: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 519-519: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 563-563: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 568-568: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 589-589: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 595-595: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 646-646: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 654-654: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 661-661: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 748-748: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 770-770: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 779-779: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 787-787: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 794-794: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 822-822: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 832-832: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 840-840: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 850-850: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 872-872: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 880-880: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 893-893: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 900-900: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 931-931: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 939-939: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 992-992: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1017-1017: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1025-1025: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1035-1035: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1043-1043: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1054-1054: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1087-1087: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1098-1098: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1156-1156: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1165-1165: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1190-1190: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1200-1200: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1222-1222: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1238-1238: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1250-1250: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1270-1270: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1276-1276: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1301-1301: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1319-1319: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1331-1331: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1350-1350: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1364-1364: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1384-1384: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1387-1387: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1471-1471: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1503-1503: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1516-1516: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1530-1530: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1543-1543: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1556-1556: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1567-1567: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1615-1615: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1638-1638: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1716-1716: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1732-1732: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1776-1776: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1795-1795: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1830-1830: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1843-1843: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1855-1855: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1871-1871: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 1962-1962: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 2002-2002: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 2080-2080: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 2102-2102: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 2110-2110: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 2122-2122: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 2130-2130: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 2137-2137: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 2168-2168: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 2176-2176: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 2184-2184: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 2195-2195: 'error' is defined but never used.

(@typescript-eslint/no-unused-vars)


[error] 2199-2199: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)

🔇 Additional comments (32)
package.json (3)

3-3: Version bump indicates stable API is approaching

The change from 0.4.0 to 1.0.0-beta.3 signifies this library is nearing a stable 1.0 release. This is appropriate given the comprehensive Developer Platform API being introduced.


44-45: Updated type definitions to match React 19

Updating TypeScript definitions to match React 19 is necessary for TypeScript users working with the latest React version. This ensures type safety with the newer API.


27-28:

✅ Verification successful

Expanded React compatibility is good practice

Broadening peer dependencies to support both React 18 and 19 versions is a forward-thinking approach. This allows users to adopt the library regardless of which React version they're using.


🌐 Web query:

When was React 19 released?

💡 Result:

React 19, the latest major version of the React JavaScript library, was officially released as stable on December 5, 2024[1][4][5][6][8]. This release followed a beta phase and a release candidate (RC) announced earlier in April 2024[7][9], with the React team finalizing features like Actions, Server Components, and enhanced error handling for the stable build.

Key details about the release:

  • It introduced Actions for streamlined async state management[1][5][8], Server Components for server-side rendering optimizations[4][7], and a new React Compiler (beta) for performance improvements[2][3].
  • The upgrade process emphasized backward compatibility, though some deprecated APIs like propTypes and string refs were removed[6].
  • The release marked two years since React 18, focusing on developer experience and performance[1][5].

For developers, the stable version became available via npm with npm install react@19 react-dom@19[3][6][8].

Citations:


Expanded React Compatibility Confirmed

The updated package.json now explicitly supports both React 18 and React 19. Given that React 19 was officially released on December 5, 2024, this change ensures that your library remains compatible with the latest stable version while still supporting the previous major release. This forward-thinking approach enhances usability for a broader range of developers.

src/lib/test/integration/developer.test.ts (7)

41-41: Use typed error handling instead of any for error parameters

The error parameter is correctly captured but not used in this block. Also, using any for error types bypasses TypeScript's type checking benefits.

-  } catch (loginError) {
+  } catch (loginError: unknown) {
🧰 Tools
🪛 ESLint

[error] 41-41: 'loginError' is defined but never used.

(@typescript-eslint/no-unused-vars)


59-59: Use unknown instead of any for error parameters

Using unknown type is safer than any as it requires type checking before using the error object's properties.

-    } catch (registerError: any) {
+    } catch (registerError: unknown) {
       if (
-        registerError.message.includes("Email already registered") ||
-        registerError.message.includes("User already exists")
+        registerError instanceof Error && 
+        (registerError.message.includes("Email already registered") ||
+        registerError.message.includes("User already exists"))
       ) {
🧰 Tools
🪛 ESLint

[error] 59-59: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


11-13: Good validation for test environment variables

Validating required environment variables early with descriptive error messages is a good practice. This ensures tests don't run with incomplete configuration.


15-16: Effective caching mechanism for login responses

Implementing a cache for successful login responses is a smart optimization that reduces redundant authentication requests during testing.

Also applies to: 25-27


37-38: Store authentication tokens more securely

While localStorage is used throughout the tests for token storage, consider using more secure alternatives in production environments.

Based on the retrieved learning from AnthonyRonning, I understand that more secure token storage methods (using httpOnly cookies or other secure storage) are already planned for a future update of the OpenSecret-SDK. This is an appropriate roadmap decision.

Also applies to: 54-56


1903-1907: Well-structured test for secret management

The tests for secret management are well-structured with proper setup, assertions, and cleanup. The loop pattern for creating multiple test secrets is clean and maintainable.


111-127: Comprehensive authentication state verification

The test includes thorough validation of both the user information and organization data returned from the Me endpoint, ensuring all expected fields are present and of the correct type.

src/lib/developer.tsx (5)

42-421: Excellent type definitions and documentation

The comprehensive TypeScript interface definitions with detailed JSDoc comments provide excellent developer documentation. Each method's purpose, parameters, return types, and error cases are clearly explained.


498-506: Well-structured component props with defaults

The OpenSecretDeveloper component has clearly defined props with appropriate types and defaults where needed. The required apiUrl prop enforces proper configuration.


512-526: Good validation of API URL

The component properly validates the apiUrl parameter and throws a descriptive error if it's missing or empty, preventing silent failures.


557-571: Robust attestation verification implementation

The getAttestationDocument function properly fetches, authenticates, and parses the attestation document with appropriate error handling, providing a complete security verification flow.


423-479: Good default context implementation with error messages

The default context implementation throws descriptive errors when methods are called outside of the provider, helping developers identify integration issues quickly.

docs/PLATFORM.md (7)

1-4: Clear introduction to the Developer Platform API

The introduction succinctly describes the purpose and scope of the Developer Platform API, setting appropriate context for the documentation that follows.


9-22: Good initialization example with all required props

The example clearly demonstrates how to initialize the OpenSecretDeveloper component with the required apiUrl and optional pcrConfig parameters.


24-119: Comprehensive type reference

The types section provides a thorough reference of all data structures used in the API, which is invaluable for developers integrating with the platform.


294-305: Important authentication state documentation

The documentation clearly explains how authentication tokens are stored and managed, and how to check the authentication state, which is crucial for implementing auth flows.


307-594: Comprehensive API method documentation

The documentation thoroughly covers all available methods with their parameters, return types, and purpose, organized into logical functional groups.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~327-~327: Loose punctuation mark.
Context: ...... } ``` ### Developer State - auth: An object containing the current develo...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~338-~338: Loose punctuation mark.
Context: ...string): Promise`: Signs in a developer with the provided ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~339-~339: Loose punctuation mark.
Context: ...string): Promise`: Registers a new developer account with ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~340-~340: Loose punctuation mark.
Context: ...ly updated. - signOut(): Promise<void>: Signs out the current developer by remo...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~341-~341: Loose punctuation mark.
Context: ...l. - refetchDeveloper(): Promise<void>: Refreshes the developer's authenticatio...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~342-~342: Loose punctuation mark.
Context: ...erifyEmail(code: string): Promise`: Verifies a developer's email address us...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~343-~343: Loose punctuation mark.
Context: ...ionCode(): Promise<{ message: string }>`: Requests a new verification email to be...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~344-~344: Loose punctuation mark.
Context: ...onEmail(): Promise<{ message: string }>: Alias for requestNewVerificationCode()...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~345-~345: Loose punctuation mark.
Context: ...g, hashedSecret: string): Promise`: Initiates the password reset process fo...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~346-~346: Loose punctuation mark.
Context: ...: string): Promise<{ message: string }>`: Completes the password reset process fo...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~347-~347: Loose punctuation mark.
Context: ...: string): Promise<{ message: string }>`: Changes the password for an authenticat...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~351-~351: Loose punctuation mark.
Context: ... Attestation Verification - pcrConfig: An object containing additional PCR0 ha...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~352-~352: Loose punctuation mark.
Context: ... to validate against. - getAttestation: Gets attestation from the enclave. - `a...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~353-~353: Loose punctuation mark.
Context: ...ation from the enclave. - authenticate: Authenticates an attestation document. ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~354-~354: Loose punctuation mark.
Context: ...on document. - parseAttestationForView: Parses an attestation document for view...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~355-~355: Loose punctuation mark.
Context: ...document for viewing. - awsRootCertDer: AWS root certificate in DER format. - `...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~356-~356: Loose punctuation mark.
Context: ... in DER format. - expectedRootCertHash: Expected hash of the AWS root certifica...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~357-~357: Loose punctuation mark.
Context: ...ertificate. - getAttestationDocument(): Gets and verifies an attestation docume...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~381-~381: Loose punctuation mark.
Context: ...on(name: string): Promise`: Creates a new organization with the giv...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~382-~382: Loose punctuation mark.
Context: ...rganizations(): Promise<Organization[]>`: Lists all organizations the developer h...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~383-~383: Loose punctuation mark.
Context: ...anization(orgId: string): Promise`: Deletes an organization (requires owner...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~414-~414: Loose punctuation mark.
Context: ...description?: string): Promise`: Creates a new project within an organiz...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~415-~415: Loose punctuation mark.
Context: ...ects(orgId: string): Promise<Project[]>`: Lists all projects within an organizati...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~416-~416: Loose punctuation mark.
Context: ...g, projectId: string): Promise: Gets a single project by ID. - updateP...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~417-~417: Loose punctuation mark.
Context: ...g; status?: string }): Promise: Updates project details. - deleteProje...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~418-~418: Loose punctuation mark.
Context: ...ring, projectId: string): Promise`: Deletes a project. Example: ```tsx con...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~458-~458: It seems likely that a singular genitive (’s) apostrophe is missing.
Context: ...updated_at: string; }; ``` ### Project Secrets API Methods - `createProjectSecret(org...

(AI_HYDRA_LEO_APOSTROPHE_S_XS)


[uncategorized] ~460-~460: Loose punctuation mark.
Context: ...secret: string): Promise`: Creates a new secret for a project. The...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~461-~461: Loose punctuation mark.
Context: ...ctId: string): Promise<ProjectSecret[]>: Lists all secrets for a project. - del...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~462-~462: Loose punctuation mark.
Context: ...string, keyName: string): Promise`: Deletes a project secret. Example: ```...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~501-~501: Loose punctuation mark.
Context: ...jectId: string): Promise`: Gets email configuration for a project....

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~502-~502: Loose punctuation mark.
Context: ... EmailSettings): Promise`: Updates email configuration. Example: ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~540-~540: Loose punctuation mark.
Context: ...jectId: string): Promise: Gets OAuth settings for a project. - u...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~541-~541: Loose punctuation mark.
Context: ... OAuthSettings): Promise`: Updates OAuth configuration. Example: ...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~587-~587: Loose punctuation mark.
Context: ...?: string): Promise`: Creates an invitation to join an organi...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~588-~588: Loose punctuation mark.
Context: ... string): Promise<OrganizationMember[]>`: Lists all members of an organization. -...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~589-~589: Loose punctuation mark.
Context: ... string): Promise<OrganizationInvite[]>`: Lists all pending invitations for an or...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~590-~590: Loose punctuation mark.
Context: ...e: string): Promise`: Gets a specific invitation by UUID code...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~591-~591: Loose punctuation mark.
Context: ...: string): Promise<{ message: string }>: Deletes an invitation. - updateMemberR...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~592-~592: Loose punctuation mark.
Context: ...e: string): Promise: Updates a member's role. - removeMembe...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~593-~593: Loose punctuation mark.
Context: ... string, userId: string): Promise`: Removes a member from the organization....

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~594-~594: Loose punctuation mark.
Context: ...: string): Promise<{ message: string }>`: Accepts an organization invitation. Ex...

(UNLIKELY_OPENING_PUNCTUATION)


465-485: Good example with proper encoding for secrets

The secret creation example correctly demonstrates the necessary base64 encoding step, which is a security-critical aspect of secret management.


658-779: Excellent complete example implementation

The complete example showcases a real-world implementation of the Developer Portal, including organization and project management, creating a practical starting point for developers.

src/lib/platformApi.ts (10)

1-105: Comprehensive type definitions.
These type declarations provide clear structures for all platform entities (e.g., user, organization, project). They’re well-organized and align with best practices for TypeScript models.


157-194: Duplicate comment: Storing tokens in localStorage.
Storing access/refresh tokens in localStorage can introduce security risks if an XSS vulnerability exists. Evaluate using HTTP-only cookies or another more secure mechanism.


195-219: Organization management looks good.
The CRUD functions (createOrganization, listOrganizations, deleteOrganization) are clearly defined and straightforward.


220-268: Project management implementation is clear.
These create, list, get, update, and delete operations follow a consistent pattern. Great job keeping the API calls uniform.


285-327: Secure handling of project secrets.
createProjectSecret enforces base64-encoded secrets, and listProjectSecrets returns only metadata. This design follows best practices by never exposing raw secrets.


328-369: Email and OAuth settings are well-defined.
Providing separate functions for retrieval and updates keeps the code modular and clear.


370-445: Organization membership and invite flows.
Validation for empty emails and separate endpoints for invites/membership updates look clean and maintainable.


446-488: User profile and invite acceptance.
acceptInvite, platformMe, verifyPlatformEmail, and requestNewPlatformVerificationCode are cohesive, covering essential account flows.


489-556: Comprehensive password reset flow.
requestPlatformPasswordReset and confirmPlatformPasswordReset handle the full verification chain with hashed and plaintext secrets. This is a robust approach to secure password resetting.


557-585: Final password change function is straightforward.
changePlatformPassword completes the user’s credentials management. Implementation is consistent with the rest of the file.

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.

1 participant