Skip to content

docs: add Certified ATProto integration spec and topology memo - #640

Open
Oba-One wants to merge 1 commit into
developfrom
research/certified-atproto-exploration
Open

docs: add Certified ATProto integration spec and topology memo#640
Oba-One wants to merge 1 commit into
developfrom
research/certified-atproto-exploration

Conversation

@Oba-One

@Oba-One Oba-One commented Jul 16, 2026

Copy link
Copy Markdown
Member

Important

DO NOT CLOSE — this PR is deliberately parked open as a tracking artifact.
It is not stale. It tracks planned identity work that has not been scheduled yet.
Automated agents and repo-hygiene sweeps must leave it open; only a human may close it.
Durable tracker: PRD-761 · label: keep-open

Summary

Adds two planning docs for a potential Green Goods × Certified (AT Protocol) identity integration — the output of a research/spec exploration. Both are unlisted and feature_status: Planned (implementation not approved).

Docs

  • certified-atproto-integration-spec-2026-07.md — full integration spec: Certified owns the DID/PDS, Green Goods acts as an AT Protocol OAuth client that mirrors approved EAS attestations into hypercerts-lexicon records. Covers executive decisions, premise corrections, schema mapping, and evidence.
  • certified-atproto-topology-memo-2026-07.md — the shorter identity-topology + trust-boundaries decision memo (Pattern A, user-delegated PDS writes), with a mermaid topology, OAuth dependency analysis, and approval gates.

Both use [D]/[I]/[S] claim labels (Documented / Inferred / Speculative) and cite repo + upstream (hypercerts-lexicon v1.1.0, Certified, AT Protocol) evidence.

Validation

  • bun run build:docs ✅ — Docusaurus build succeeds; the relative cross-link between the two specs resolves.
  • Rebased onto develop 2026-07-28 (e8ee6d3): Build Docs ✅ · CI Gate ✅, zero conflicts.

Notes

  • Docs-only; no runtime code. Pages are unlisted, so they don't appear in site navigation.
  • Both files are net-new paths under docs/docs/builders/specs/, so this branch cannot textually conflict with develop.

🤖 Generated with Claude Code

@vercel

vercel Bot commented Jul 16, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

3 Skipped Deployments
Project Deployment Actions Updated (UTC)
green-goods Skipped Skipped Jul 16, 2026 2:22am
green-goods-admin Skipped Skipped Jul 16, 2026 2:22am
green-goods-design Skipped Skipped Jul 16, 2026 2:22am

Request Review

@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Two new documentation pages define the Certified ATProto identity topology and the detailed integration specification, covering OAuth delegation, EAS-to-PDS mirroring, provenance signing, record mapping, privacy constraints, milestones, and validation evidence.

Changes

Certified ATProto integration

Layer / File(s) Summary
Topology and integration decisions
docs/docs/builders/specs/certified-atproto-...md
Defines Pattern A, identity ownership, trust boundaries, claim labels, and the Pattern C boundary.
Identity, OAuth, and address linking
docs/docs/builders/specs/certified-atproto-...md
Documents OAuth flows, profile and garden handling, address consent, and platform provenance configuration.
EAS mirroring and record integrity
docs/docs/builders/specs/certified-atproto-...md
Specifies queued mirroring, lexicon mapping, signing, deterministic writes, reconciliation, proof options, and visibility rules.
Milestones and validation evidence
docs/docs/builders/specs/certified-atproto-...md
Adds phased milestones, acceptance criteria, approval gates, open questions, validation commands, and evidence references.

Estimated code review effort: 2 (Simple) | ~10 minutes

Poem

I’m a rabbit with a PDS to hop,
OAuth scopes make the carrots drop.
EAS receipts line up in a queue,
Signed little records wait their cue.
Gardens, links, and proofs take flight—
Two fresh specs make the path clear and bright!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly matches the main change: adding two Certified ATProto documentation pages.
Description check ✅ Passed The description is directly about the two new planning docs and their docs-only validation, so it aligns with the changeset.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch research/certified-atproto-exploration

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Oba-One commented Jul 16, 2026

Copy link
Copy Markdown
Member Author

Review summary

Invariants checked: 9 from CLAUDE.md / AGENTS.md
Inline flags: 0
Verdict: APPROVE

Docs-only PR: two new files under docs/docs/builders/specs/, both unlisted: true + feature_status: Planned, 946 insertions / 0 deletions, no runtime code.

Notes:

  • Hook / indexer / address-typing / deployment-artifact / barrel-import / contract-test / CI-lane boundaries — not applicable; no packages/** source, indexer handlers, .sol files, or .github/workflows/** touched.
  • Raw forge commands (inv. 4) — none present.
  • bun test vs bun run test (inv. 8) — no bun test occurrences.
  • Hardcoded addresses (inv. 5) — no 0x… address literals; no deep @green-goods/shared/{dist,src} imports.
  • The spec maps EAS attestations → hypercerts-lexicon records and references Hypercert linkage, but purely as documentation of a proposed, unapproved integration — no Envio indexer handler is added, so the indexer boundary (inv. 2) is not crossed.
  • No frontend surfaces touched → Vercel preview (skipped by Vercel, as expected for docs) and Sentry enrichment are not applicable.

Clean docs/spec change. Nothing blocking.


Generated by Claude Code

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4617f4119e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +375 to +379
| Option | Feasibility | Benefit | Cost or loss | Recommendation | Claim |
| ----------------------------------------------------------- | ------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | ------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | ------------------------------ | --- |
| A. ERC-1271 proof variant | A deployed Kernel can validate a signature through `isValidSignature` over a defined digest | Cryptographically binds the Certified DID to the actual Green Goods account | Requires new lexicon union variant, exact digest and chain rules, deployed account, RPC verification, and upstream acceptance | Durable deployed-account path | [I] |
| B. ERC-6492 proof variant | Wrapper can prove a counterfactual smart-account signature plus deployment data | Supports links before Kernel deployment | More complex verification, factory/init-code trust, size constraints, and upstream acceptance | Durable counterfactual companion to A | [I] |
| C. Link the underlying P-256 authenticator or a session key | The authenticator controls Kernel authorization but does not equal the Kernel address | Avoids new smart-account proof at first glance | WebAuthn signs `authenticatorData | | SHA256(clientDataJSON)`, not raw EIP-712 digests or record CID bytes. A session key is transient and binds the wrong identity | Reject for DID-to-account link | [D] |

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Fix malformed options table rendering

When the docs site renders this page, the whole smart-account options matrix is emitted as raw pipe-delimited text instead of a table because the separator row has eight columns while the header has six, and row C adds more unescaped | characters inside the WebAuthn expression. This makes the passkey-link tradeoff section hard to read in the generated Docusaurus page even though bun run build:docs exits successfully.

Useful? React with 👍 / 👎.


- a real Certified test account authorizes the Green Goods client
- client metadata and redirect URIs are accepted by `certified.one`
- exact granular create/update scopes are demonstrated with create, read-back, update, and delete cleanup in a test repository

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Align cleanup with the requested repo scopes

This gate asks implementers to prove delete cleanup while also calling the exact create/update scopes the target permission set. In AT Protocol repo scopes, delete is a separate action qualifier, so a client authorized only for action=create&action=update should be rejected when it tries to delete test records; either request delete in a test-only scope or make cleanup use an allowed operation.

Useful? React with 👍 / 👎.


| Green Goods source | Lexicon record and fields | Relationship and cross-reference | Validation or loss | Claim |
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----- |
| Garden | `org.hypercerts.collection`: `type = project`, `title = name`, `shortDescription` or `description`, `banner`, `createdAt`, optional `location` strongRef | Deterministic collection rkey from chain ID plus Garden address. Add Work activities as weighted or unweighted `items` strongRefs | `collection` supports multiple project records and recursive nesting. It has no GardenAccount, Hats, or role fields | [I] |

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Wrap collection items before writing them

The v1.1.0 org.hypercerts.collection schema does not store items as direct strongRefs; each entry must be a collection#item object with itemIdentifier and optional itemWeight. If milestone-two implementation follows this crosswalk literally, Garden collection writes will fail schema validation or be unable to represent weights.

Useful? React with 👍 / 👎.

Comment on lines +324 to +327
| Work media CID | `org.hypercerts.context.attachment`: `subjects = [activity strongRef]`, `contentType = evidence`, `content = ipfs://<cid>`, title, createdAt | Attachment points to activity | Copy only media approved for public PDS visibility | [I] |
| Work metadata CID | `attachment` with `contentType = methodology` or `evidence`, `content = ipfs://<cid>` | Attachment points to activity | Use `methodology` only when the content actually describes method. Otherwise use `evidence` | [I] |
| Work numeric detail | `org.hypercerts.context.measurement`: `subjects`, `metric`, `unit`, numeric-string `value`, time, optional evidence URIs and measurer DIDs | Measurement points to activity; evaluation can later reference it | Mirror only typed numeric values with an explicit unit. Current arbitrary details are not automatically valid measurements | [I] |
| Work EAS source | `attachment`: subject activity, `contentType = evidence`, `content` contains a stable HTTPS EAS viewer URI, title contains schema identity, createdAt from chain | Deterministic rkey from `eip155:<chainId>:eas:<uid>` | This carries chain ID and UID without inventing lexicon fields | [I] |

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Model attachment content as URI arrays

The attachment schema defines content as an array of union items such as { uri: ... }, not as a scalar URI string. Following these rows literally would produce invalid media, metadata, and EAS-source attachment records that the lexicon validator or PDS should reject.

Useful? React with 👍 / 👎.

5. SHA-256 hash the encoded bytes and construct CIDv1 with DAG-CBOR codec `0x71`. The result is 36 bytes: CID version, codec, multihash identifier, length, and 32-byte digest.
6. ECDSA-sign those CID bytes with the stable P-256 key. A KMS adapter may submit the raw CID bytes with its SHA-256 ECDSA algorithm, or submit `SHA256(cidBytes)` as a digest, but it must not hash twice.
7. Convert KMS DER output to raw 64-byte `r || s` and normalize `s` to the low-S form required by BIP-0062.
8. Attach `{ $type: "app.certified.signature.defs#inline", signature, key }` under `signatures`.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Wrap inline signatures in the required list

The hypercerts lexicon defines each record's signatures field as app.certified.signature.defs#list, i.e. an array of inline signatures or strongRefs. If implementers attach the single inline object directly as written here, otherwise valid signed records will fail schema validation when the client tries to write them to the PDS.

Useful? React with 👍 / 👎.

| Work metadata CID | `attachment` with `contentType = methodology` or `evidence`, `content = ipfs://<cid>` | Attachment points to activity | Use `methodology` only when the content actually describes method. Otherwise use `evidence` | [I] |
| Work numeric detail | `org.hypercerts.context.measurement`: `subjects`, `metric`, `unit`, numeric-string `value`, time, optional evidence URIs and measurer DIDs | Measurement points to activity; evaluation can later reference it | Mirror only typed numeric values with an explicit unit. Current arbitrary details are not automatically valid measurements | [I] |
| Work EAS source | `attachment`: subject activity, `contentType = evidence`, `content` contains a stable HTTPS EAS viewer URI, title contains schema identity, createdAt from chain | Deterministic rkey from `eip155:<chainId>:eas:<uid>` | This carries chain ID and UID without inventing lexicon fields | [I] |
| WorkApproval | `org.hypercerts.context.evaluation`: `subject = activity strongRef`, `evaluators`, `summary`, `score { min: "0", max: "3", value: confidence }`, optional content attachment | Evaluation references activity snapshot | `evaluators` require DIDs. Do not place an EVM address in a DID field. No exact approved boolean or verification-method field exists, so this mapping is lossy | [I] |

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Serialize evaluation scores as strings

The v1.1.0 evaluation score object requires min, max, and value to be strings, while Green Goods' approval confidence field is a number. If this crosswalk is implemented literally with value: confidence, WorkApproval evaluation records will be rejected by lexicon validation instead of being written.

Useful? React with 👍 / 👎.

Oba-One commented Jul 27, 2026

Copy link
Copy Markdown
Member Author

Closing this exploration PR as stale/superseded by the current .plans execution truth and live Linear roadmap. The research and discussion remain preserved here for future reference; none of the proposed implementation was approved or merged.

@Oba-One Oba-One closed this Jul 27, 2026
@Oba-One Oba-One reopened this Jul 28, 2026
Planning docs for a potential Green Goods x Certified (AT Protocol) identity
integration: Certified owns the DID/PDS while Green Goods acts as an OAuth
client that mirrors approved EAS attestations into hypercerts-lexicon records.
Both are unlisted / feature_status: Planned (exploration output, implementation
not approved), with [D]/[I]/[S] claim labels and cited evidence.

- certified-atproto-integration-spec-2026-07.md — full integration spec.
- certified-atproto-topology-memo-2026-07.md — identity topology + trust
  boundaries decision memo.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@Oba-One
Oba-One force-pushed the research/certified-atproto-exploration branch from 4617f41 to e8ee6d3 Compare July 28, 2026 06:09
@vercel
vercel Bot temporarily deployed to Preview – green-goods-admin July 28, 2026 06:09 Inactive
@vercel
vercel Bot temporarily deployed to Preview – green-goods July 28, 2026 06:09 Inactive
@vercel
vercel Bot temporarily deployed to Preview – green-goods-design July 28, 2026 06:09 Inactive
@Oba-One Oba-One added keep-open Parked open as a tracking artifact. Agents MUST NOT close — human only. documentation Improvements or additions to documentation labels Jul 28, 2026
@Oba-One

Oba-One commented Jul 28, 2026

Copy link
Copy Markdown
Member Author

Reopened — the close on 2026-07-27 was a mistake

This PR was closed on 2026-07-27T01:30Z as "stale/superseded by the current .plans execution truth and live Linear roadmap". That call was wrong:

  • It wasn't stale. The PR was deliberately parked open as the tracking artifact for planned AT Protocol identity work.
  • Nothing superseded it. There is no .plans hub for AT Protocol or identity, and there was no Linear record carrying it forward. Closing it would have silently dropped the work — the two spec docs exist nowhere on main or develop.

The close was made by an automated agent (chatgpt-codex-connector) during an unrelated hygiene pass, not by a human decision about this work.

What changed

  • Reopened.
  • Rebased onto develop (4617f41e8ee6d3) — zero conflicts; both files are net-new paths, so this branch cannot textually conflict.
  • CI green on the rebased head: Build Docs ✅ · CI Gate ✅.
  • Durable tracker created: PRD-761. The exploration no longer depends on this PR staying open.
  • Labeled keep-open and banner added to the description, so future sweeps have an explicit machine-readable signal.

Known drift to resolve before any merge

The specs use "operator" vocabulary, which the Operator → Steward rename supersedes. Not a CI failure (lint:vocab only scopes i18n JSON), but it should be reconciled if this ever merges.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/docs/builders/specs/certified-atproto-integration-spec-2026-07.md`:
- Around line 375-379: Fix the Markdown table around the Option/Feasibility
headers so the separator row defines exactly six columns, matching the header.
In the row for “Link the underlying P-256 authenticator or a session key,”
replace the raw pipe within the WebAuthn expression with Markdown-safe text so
it remains within the Claim column.
- Around line 82-89: Update the unlink and cleanup scope definitions in the
certified integration specification, including the sections around the
address-link rule and the referenced later sections, to include action=delete
alongside action=create and action=update. If deletion remains outside
repository scopes, explicitly define unlink and cleanup as owner-mediated or
out-of-band flows instead.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: f72bed19-fbeb-48a6-9cc6-4d4f4defb3f1

📥 Commits

Reviewing files that changed from the base of the PR and between 8fd89e6 and e8ee6d3.

📒 Files selected for processing (2)
  • docs/docs/builders/specs/certified-atproto-integration-spec-2026-07.md
  • docs/docs/builders/specs/certified-atproto-topology-memo-2026-07.md
📜 Review details
⏰ Context from checks skipped due to timeout. (3)
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: CI Gate
🧰 Additional context used
📓 Path-based instructions (1)
**/*

📄 CodeRabbit inference engine (CLAUDE.md)

**/*: Before claiming a fix, setting, or behavior works, produce evidence in the same turn; if verification is unavailable, state that it cannot be verified instead of declaring success.
For destructive changes, list what will be removed and added and wait for user confirmation; do not replace requested additions or edit files when the user asks only for chat output.
Stay on the current branch unless explicitly instructed otherwise; stash unknown diffs rather than reverting or deleting them, and investigate concurrent-agent changes before destructive operations.
Remove temporary files, scripts, and helpers created during iteration before reporting completion.
Local agentic browser QA must use the authenticated Brave QA profile; if it is unreachable, report QA as blocked rather than substituting isolated Playwright, clean-room, or unauthenticated browser evidence.
Use the lightest honest validation for the user's intent: targeted proof for QA fixes, the Repo Quick Gate for shared or cross-package changes, and the Ship Gate only for explicit release or merge readiness.
Use Linear for durable backlog work and never open GitHub Issues for backlog work; respect the documented team, project, label, and privacy-routing rules.
Always call PostHog switch-project before querying; select the project based on the reported surface and keep replay URLs, session IDs, distinct IDs, wallet addresses, and reporter identifiers out of Linear bodies.
For ambiguous, multi-package, or high-risk work, research first, record evidence, plan the smallest implementation path, identify human judgment points, then edit.
For multi-issue or ambiguous cleanup work, follow the repository health ritual: /audit, scope lock, /clean, /review, and /ship as applicable.

**/*: Use bun for repository scripts and package operations; the only npm exception is npm run setup on a fresh machine before Bun is available.
Use bun run test, never bun test. Never invoke raw forge; use the repo...

Files:

  • docs/docs/builders/specs/certified-atproto-topology-memo-2026-07.md
  • docs/docs/builders/specs/certified-atproto-integration-spec-2026-07.md
🔇 Additional comments (1)
docs/docs/builders/specs/certified-atproto-topology-memo-2026-07.md (1)

1-152: LGTM!

Comment on lines +82 to +89
**[S]** Address-link rule:

- construct a deterministic record key from the normalized address and proof variant
- require an explicit consent action by that exact account
- retain earlier records when the active mode changes
- permit a user-requested unlink by deleting or superseding the individual record, subject to Certified conventions
- never infer a Kernel link from an EOA proof, or an EOA link from an OAuth session
- show the linked mode and address before submission

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

Confirm that AT Protocol repository permissions require an explicit action=delete permission for client-side record deletion.

💡 Result:

The AT Protocol repository permission system allows for granular control over client-side operations, including record deletion [1][2]. When defining permissions for a repository (typically within an OAuth scope or a Permission Set), the optional 'action' parameter is used to specify which operations are permitted [1][3]. The supported actions are 'create', 'update', and 'delete' [1][3]. If the 'action' parameter is omitted from a permission definition, all three operations—create, update, and delete—are granted by default [1][2][4]. However, if you wish to restrict a client to only specific operations (e.g., preventing record deletion), you must explicitly define the allowed actions [1][4]. In such a case, to permit deletion, 'action=delete' must be included in the permission string [1][2]. Conversely, if 'action=delete' is excluded from the list of specified actions, the client will not be authorized to perform record deletions [2][4]. In summary, while 'action=delete' is not strictly required for all repository access (as it is included by default if unspecified), it is a required explicit action if you are defining a restricted permission set that is intended to include the ability to delete records [1][4].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

file="docs/docs/builders/specs/certified-atproto-integration-spec-2026-07.md"

echo "== file exists and line count =="
wc -l "$file"

echo "== relevant occurrences =="
rg -n "action=|scope|delete|unlink|Milestone 0|OAuth|permission" "$file" || true

echo "== sections around proposed lines =="
sed -n '70,105p' "$file"
echo "---"
sed -n '180,210p' "$file"
echo "---"
sed -n '515,535p' "$file"

Repository: greenpill-dev-guild/green-goods

Length of output: 19446


Add action=delete to the unlink/cleanup scopes.

The link rule lets unlink via deletion, and Milestone 0 requires delete cleanup, but the requested repo scopes only include action=create&action=update. Since granular action-qualified scopes restrict repository operations outside the allowed value, add action=delete to the unlink-related collections or explicitly define unlink and cleanup as owner-mediated/out-of-band flows.

Also applies to Lines: 192-199, 527 and Lines: 521-527.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/docs/builders/specs/certified-atproto-integration-spec-2026-07.md`
around lines 82 - 89, Update the unlink and cleanup scope definitions in the
certified integration specification, including the sections around the
address-link rule and the referenced later sections, to include action=delete
alongside action=create and action=update. If deletion remains outside
repository scopes, explicitly define unlink and cleanup as owner-mediated or
out-of-band flows instead.

Source: MCP tools

Comment on lines +375 to +379
| Option | Feasibility | Benefit | Cost or loss | Recommendation | Claim |
| ----------------------------------------------------------- | ------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | ------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | ------------------------------ | --- |
| A. ERC-1271 proof variant | A deployed Kernel can validate a signature through `isValidSignature` over a defined digest | Cryptographically binds the Certified DID to the actual Green Goods account | Requires new lexicon union variant, exact digest and chain rules, deployed account, RPC verification, and upstream acceptance | Durable deployed-account path | [I] |
| B. ERC-6492 proof variant | Wrapper can prove a counterfactual smart-account signature plus deployment data | Supports links before Kernel deployment | More complex verification, factory/init-code trust, size constraints, and upstream acceptance | Durable counterfactual companion to A | [I] |
| C. Link the underlying P-256 authenticator or a session key | The authenticator controls Kernel authorization but does not equal the Kernel address | Avoids new smart-account proof at first glance | WebAuthn signs `authenticatorData | | SHA256(clientDataJSON)`, not raw EIP-712 digests or record CID bytes. A session key is transient and binds the wrong identity | Reject for DID-to-account link | [D] |

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Fix the Markdown table column definition.

The header has six columns, but the separator row defines seven. Normalize the separator and avoid using a raw pipe in the WebAuthn cell so the rendered table cannot shift columns.

Proposed fix
-| ----------------------------------------------------------- | ----------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | ------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | ------------------------------ | --- |
+| ----------------------------------------------------------- | ----------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | ------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
...
-| C. Link the underlying P-256 authenticator or a session key | ... | ... | WebAuthn signs `authenticatorData | SHA256(clientDataJSON)`, not raw EIP-712 digests or record CID bytes. ... | Reject for DID-to-account link | [D] |
+| C. Link the underlying P-256 authenticator or a session key | ... | ... | WebAuthn signs `authenticatorData` concatenated with `SHA256(clientDataJSON)`, not raw EIP-712 digests or record CID bytes. ... | Reject for DID-to-account link | [D] |
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
| Option | Feasibility | Benefit | Cost or loss | Recommendation | Claim |
| ----------------------------------------------------------- | ------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | ------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | ------------------------------ | --- |
| A. ERC-1271 proof variant | A deployed Kernel can validate a signature through `isValidSignature` over a defined digest | Cryptographically binds the Certified DID to the actual Green Goods account | Requires new lexicon union variant, exact digest and chain rules, deployed account, RPC verification, and upstream acceptance | Durable deployed-account path | [I] |
| B. ERC-6492 proof variant | Wrapper can prove a counterfactual smart-account signature plus deployment data | Supports links before Kernel deployment | More complex verification, factory/init-code trust, size constraints, and upstream acceptance | Durable counterfactual companion to A | [I] |
| C. Link the underlying P-256 authenticator or a session key | The authenticator controls Kernel authorization but does not equal the Kernel address | Avoids new smart-account proof at first glance | WebAuthn signs `authenticatorData | | SHA256(clientDataJSON)`, not raw EIP-712 digests or record CID bytes. A session key is transient and binds the wrong identity | Reject for DID-to-account link | [D] |
| Option | Feasibility | Benefit | Cost or loss | Recommendation | Claim |
| ----------------------------------------------------------- | ------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | ------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| A. ERC-1271 proof variant | A deployed Kernel can validate a signature through `isValidSignature` over a defined digest | Cryptographically binds the Certified DID to the actual Green Goods account | Requires new lexicon union variant, exact digest and chain rules, deployed account, RPC verification, and upstream acceptance | Durable deployed-account path | [I] |
| B. ERC-6492 proof variant | Wrapper can prove a counterfactual smart-account signature plus deployment data | Supports links before Kernel deployment | More complex verification, factory/init-code trust, size constraints, and upstream acceptance | Durable counterfactual companion to A | [I] |
| C. Link the underlying P-256 authenticator or a session key | The authenticator controls Kernel authorization but does not equal the Kernel address | Avoids new smart-account proof at first glance | WebAuthn signs `authenticatorData` concatenated with `SHA256(clientDataJSON)`, not raw EIP-712 digests or record CID bytes. A session key is transient and binds the wrong identity | Reject for DID-to-account link | [D] |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/docs/builders/specs/certified-atproto-integration-spec-2026-07.md`
around lines 375 - 379, Fix the Markdown table around the Option/Feasibility
headers so the separator row defines exactly six columns, matching the header.
In the row for “Link the underlying P-256 authenticator or a session key,”
replace the raw pipe within the WebAuthn expression with Markdown-safe text so
it remains within the Claim column.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e8ee6d314d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".


**[I]** The exact mirror trigger is after a confirmed receipt and successful extraction of the EAS `Attested` event UID. It must be before the Work job is deleted. The transaction hash is not an EAS UID and must not continue to be stored as though it were one.

**[S]** Add a shared receipt helper that waits for the receipt and parses the EAS `Attested(recipient, attester, uid, schemaUID)` event. In one IndexedDB transaction, persist the UID-to-transaction mapping and insert the mirror job, then mark or remove the Work job. If the browser stops between confirmation and that transaction, a recovery pass queries the receipt by transaction hash.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Resolve Safe identifiers before receipt recovery

When a wallet submission uses the supported Safe-style path, packages/shared/src/modules/transactions/wallet-sender.ts:103-115 deliberately returns a non-canonical identifier without waiting for a receipt. This helper cannot query an EVM receipt with that value, so it cannot extract the EAS UID or recover after interruption as specified; the milestone needs a Safe-specific resolution/pending path before treating the Work job as confirmed.

Useful? React with 👍 / 👎.


| Green Goods source | Lexicon record and fields | Relationship and cross-reference | Validation or loss | Claim |
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----- |
| Garden | `org.hypercerts.collection`: `type = project`, `title = name`, `shortDescription` or `description`, `banner`, `createdAt`, optional `location` strongRef | Deterministic collection rkey from chain ID plus Garden address. Add Work activities as weighted or unweighted `items` strongRefs | `collection` supports multiple project records and recursive nesting. It has no GardenAccount, Hats, or role fields | [I] |

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Use a TID-compatible key for collections

The same document states at line 338 that org.hypercerts.collection is keyed by TID, so a hash-derived key based on chain ID and Garden address is not valid for this record type. Implementing this row literally would make milestone-two collection writes fail key validation; use a valid TID and persist its mapping, or define a schema-supported deterministic strategy.

Useful? React with 👍 / 👎.


**[S]** Derive each ATProto rkey as a lowercase base32 encoding of `SHA-256("gg-certified-v1" || chainId || easUid || recordRole)`, prefixed with a short alphabetic role marker. Validate the final value against AT Protocol record-key grammar before implementation. Do not place raw secrets or user identifiers in the rkey.

**[I]** This makes retry lookup deterministic without assuming the PDS supports a secondary unique index. A `putRecord` retry with the same canonical content is idempotent. Timestamps must come from the chain source or original job, not from the retry clock, or the CID changes.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Guard deterministic writes with a record precondition

When the deterministic rkey already contains a different CID—the conflict scenario listed at line 482—an unconditioned com.atproto.repo.putRecord overwrites that record rather than surfacing a conflict. A retry following this procedure can therefore destroy a user edit before reconciliation runs; require a read-and-compare or swapRecord precondition before each put.

Useful? React with 👍 / 👎.


```bash
bun run --filter @green-goods/shared test -- src/__tests__/hooks/garden/createGardenOperation.test.ts src/__tests__/stores/createGardenStore.test.ts src/__tests__/modules/certified-records.test.ts
bun run --filter @green-goods/admin test -- src/__tests__/components/Garden/DetailsStep.test.tsx src/__tests__/workflows/createGarden.test.ts

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Point validation at the existing garden workflow test

The repository test is packages/admin/src/__tests__/workflows/createGarden.test.ts, but this command filters for createGarden.test.tsx. Once the new DetailsStep test exists, the command can still succeed while silently omitting the existing garden workflow regression suite, so the filter should use the actual .ts path.

Useful? React with 👍 / 👎.


**[I]** This milestone is a contract and deployment change and therefore requires the contract skill, deployment-path review, and human approval. It must not be folded into the client-only first slice.

**[S] Validation:** use the repository's Bun contract scripts for focused resolver tests, dry-run schema registration, shared encoder tests, `bun run check:indexing-boundary`, and the full Ship Gate. Never invoke raw `forge`.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Invoke the registered indexing-boundary script

From the repository root, bun run check:indexing-boundary exits with Script not found; that name exists only in packages/indexer/package.json, while the root script is bun run indexer:check-boundary. As written, milestone-four validation stops before the boundary check or Ship Gate, so use the root alias or explicitly run the package-local command.

Useful? React with 👍 / 👎.

schemaUid: `0x${string}`;
txHash: `0x${string}`;
};
visibilityDecision: "public";

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Persist the approved publication snapshot before EAS

The mirror payload records only a generic "public" decision, but the policy later distinguishes a user-approved summary from raw feedback that must remain denied by default, and the mirror job is not created until after EAS confirmation. The signer therefore has no durable copy or digest of the exact summary and fields approved before submission, and a delayed/offline job can publish content derived under a different policy or Certified account; persist the target DID and exact approved field/content snapshot on the original Work job before sending EAS, then carry it into this payload.

Useful? React with 👍 / 👎.


### Milestone 2: Flow A garden prefill and Garden collection

**[S] Scope:** bring the same Certified session into admin, prefill blank garden fields after draft restore, and create a Garden collection after deployment.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Require a separate admin OAuth authorization

In production the client and admin run on greengoods.app and admin.greengoods.app, while the proposed browser OAuth client keeps DPoP and refresh state in IndexedDB. Browser storage is origin-scoped, so opening admin cannot restore the client PWA's "same Certified session" merely by mounting the shared provider; milestone two must specify a separate admin authorization/callback and client-metadata redirect, or change to a topology that can securely broker the session.

Useful? React with 👍 / 👎.


### 4.4 EAS path and trigger point

**[D]** Work and WorkApproval are encoded in shared code and sent through `TransactionSender`. The current job executors return only the transaction hash. The EAS transaction builder sets `refUID` to zero for Work, WorkApproval, and their batch variants.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Route online wallet Works through the mirror trigger

For an online wallet submission, packages/shared/src/hooks/work/useWorkMutation.ts:193-232 calls submitWorkDirectly; only offline wallet and non-wallet submissions enter the job queue. That direct function confirms the transaction and returns its hash without creating a queue job, so the milestone-one external-EOA path can finish EAS successfully while the queue-owned mirror trigger never runs; parse the UID and atomically enqueue the mirror from the direct path, or converge this path on the queue.

Useful? React with 👍 / 👎.

Comment on lines +563 to +564
- `packages/client/src/routes/AppShell.tsx`
- `packages/client/src/views/Login/index.tsx`

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Mount the OAuth provider above the login callback route

The current router mounts the Login route as a sibling of the protected AppShell, so adding CertifiedSessionProvider only through the listed AppShell.tsx cannot make it available while Login handles the OAuth callback. Wrapping Login separately would also violate the spec's initialize-once requirement; include PwaRuntime.tsx, Root.tsx, or another common ancestor in the plan and mount one provider above both Login and AppShell.

Useful? React with 👍 / 👎.

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

Labels

documentation Improvements or additions to documentation keep-open Parked open as a tracking artifact. Agents MUST NOT close — human only.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant