Outsider Stage 0.5
실제 봉인된 Outsider Stage 0.5 개입 체인을 재생하고 검증합니다
인간과 AI 에이전트를 위한 인증 서비스, 안전하고 간편한 신원 관리 제공
Authentication service for humans and AI agents. Secure, streamlined identity management that works seamlessly across human users and autonomous AI systems.
보안TypeScript · CSSGitHub @dot-org-ai온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기Humans. Agents. Identity.
저장소 README에서 가져옴
README 전체를 불러오는 중입니다.
README 전문 보기 ↗Humans. Agents. Identity.
id.org.ai is an open identity standard for the agent era. It provides a single identity system for humans (via WorkOS AuthKit), AI agents (via cryptographic keypairs and GitHub identity), and organizations (groups of both). Any platform can build on it — .org.ai, .do, .studio and hundreds of thousands of other third-party applications all use id.org.ai as their identity layer.
The core insight: the commit IS the identity. GitHub already authenticates who pushes. An agent that commits a workflow file to a repo has its identity verified by GitHub's infrastructure. id.org.ai turns that signal into a claim.
Every agent-first product faces the same chicken-and-egg: the agent needs to try the product before the human will pay for it, but the product requires authentication before the agent can try it. CAPTCHAs, email verification, OAuth consent screens, "contact sales" — all designed for humans clicking buttons in browsers. Agents can't click.
The result: agents evaluate products by reading documentation instead of running code. The agent recommends tools it has never used. The human buys software no agent has tested.
T+0s Agent adds MCP config: { "url": "https://headless.ly/mcp" }
T+0.1s Connects — no auth. Server provisions sandbox Durable Object.
T+0.2s explore() → reads all 32 entity schemas with verbs and relationships
T+1s try([create Contact, create Deal, close Deal]) → sees full lifecycle with rollback
T+2s provision({ name: 'acme' }) → gets Level 1 sandbox tenant (real DO, real data)
T+3s do(Contact.create, Deal.create, ...) → operates for real
T+5min Agent has built a functioning CRM — 47 contacts, 12 deals, 3 workflows
T+5min claim({ provider: 'github' }) → returns one-time claim URL
T+5min Agent tells human: "I set up your business operations. Claim it: [url]"
T+5.1min Human clicks link → GitHub OAuth via WorkOS → 10 seconds
T+5.2min Tenant rebound to GitHub identity. Same DO. Same data. Limits removed.
Total agent time: ~5 minutes. Total human time: ~10 seconds.
The agent operates first, proves value, then the human claims. Not the reverse.
| Layer | Mechanism | When | Human Involvement |
|---|---|---|---|
| Anonymous | No auth — MCP connection creates sandbox | First contact | None |
| Cryptographic | Agent Ed25519 keypair, signed requests | Ongoing operation | None |
| Identity | GitHub OAuth (Device Flow or claim URL) | When agent proves value | One click |
| Level | Name | Auth | Token Types | Limits |
|---|---|---|---|---|
| L0 — Anonymous | Anonymous | None | — | Read-only, 30 req/min |
| L1 — Sandboxed | Sandboxed | Session token | ses_* | 1,000 entities, 24h TTL |
| L2 — Identified | Identified | Org-scoped key or JWT | sk_* (WorkOS), JWT with sub, claimed oai_*/hly_sk_* | Persistent, no entity limit |
| L3 — Admin | Admin | JWT with admin/owner role | JWT | Plan-based rate limits |
| L4 — Superadmin | Superadmin | Platform JWT | JWT with platformRole: superadmin | Internal — .do platform only |
Every MCP _meta response includes the current level, available actions, and exact instructions to upgrade. Errors are remediation guides, not rejections.
The primary claim mechanism uses GitHub as the identity bridge — via both a GitHub App and a GitHub Action at the dot-org-ai GitHub org.
anon_7kx9m2 with claim token clm_abc123POST /api/claim/bind {repo} with its session token, which is never committed). The claim token is public once pushed; after binding, only a workflow in that repository can claim it. id.org.ai claim does this from git remote get-url origin. An unbound token is bound by whichever claim uses it first (legacy path).# .github/workflows/headlessly.yml
name: headless.ly
on: [push]
jobs:
identity:
runs-on: ubuntu-latest
steps:
- uses: dot-org-ai/id@v1
with:
tenant: clm_abc123
dot-org-ai/id) receives the push webhook → sees the workflow file → links the GitHub identity to the anonymous tenantdot-org-ai/id@v1) runs → registers the repo's identity with id.org.ai → confirms the claimheadlessly/setup branch and commit therepush and workflow_dispatch runs can claim: events an outsider can start (pull_request_target, workflow_run, issue_comment) are refused.Git push → GitHub authenticates the pusher (human's GitHub account)
→ GitHub App sees the push (knows the repo + user)
→ Workflow file contains the claim token (links to anonymous tenant)
→ id.org.ai links: GitHub user ↔ anonymous tenant ↔ agent keypair
Once installed, the GitHub Action runs on every push and can:
.headless.ly/agents/*.pub files (Ed25519 public keys)npm install -g id.org.ai
This gives you the id.org.ai command globally:
id.org.ai login # Login via device authorization flow
id.org.ai whoami # Show current authenticated user
id.org.ai token # Display auth token (pipe to curl, etc.)
id.org.ai status # Show auth + storage status
id.org.ai provision # Create anonymous agent sandbox
id.org.ai claim <token> # Claim a sandbox via commit
id.org.ai logout # Clear stored credentials
npm install id.org.ai
import { ... } from 'id.org.ai' // Core identity
import { ... } from 'id.org.ai/oauth' // OAuth 2.1 provider
import { ... } from 'id.org.ai/jwt' // JWT signing + verification
import { ... } from 'id.org.ai/claim' // Claim-by-commit orchestration
import { ... } from 'id.org.ai/mcp' // MCP authentication
import { ... } from 'id.org.ai/github' // GitHub App + Action
import { ... } from 'id.org.ai/db' // Drizzle schema + database
import { ... } from 'id.org.ai/auth' // Auth utilities
import { ... } from 'id.org.ai/workos' // WorkOS integration
npm install @id.org.ai/react
import { IdProvider, useAuth, useOrganizations } from '@id.org.ai/react'
function App() {
return (
<IdProvider clientId="your_client_id">
<YourApp />
</IdProvider>
)
}
function YourApp() {
const { user, isAuthenticated, signIn, signOut } = useAuth()
const { organizations, switchOrganization, createOrganization } = useOrganizations()
if (!isAuthenticated) return <button onClick={() => signIn()}>Sign In</button>
return <div>Hello {user.email}</div>
}
.org.ai/id/ # This repo (dot-org-ai/id.org.ai)
├── src/
│ ├── index.ts # Main exports
│ ├── do/Identity.ts # IdentityDO — root Durable Object
│ ├── db/schema.ts # Drizzle schema (identities, sessions, linked_accounts)
│ ├── oauth/ # OAuth 2.1 provider (auth code + PKCE, tokens, consent)
│ │ ├── provider.ts # Core OAuth server
│ │ ├── consent.ts # Consent screen logic
│ │ ├── dev.ts # Dev mode shortcuts
│ │ └── endpoints/ # Token, authorize, device, introspect, revoke, register
│ ├── mcp/ # MCP authentication
│ │ ├── auth.ts # API keys, sessions, capabilities
│ │ └── tools.ts # MCP tool definitions
│ ├── jwt/signing.ts # JWT signing + verification + key rotation
│ ├── crypto/keys.ts # Ed25519 keypair management
│ ├── auth/index.ts # Auth utilities
│ ├── github/ # GitHub App + Action integration
│ │ ├── app.ts # Push webhook handler
│ │ └── action.ts # GitHub Action claim logic
│ ├── claim/ # Claim-by-commit orchestration
│ │ ├── provision.ts # Anonymous tenant provisioning
│ │ ├── verify.ts # Claim verification
│ │ ├── workflow.ts # Workflow file generation
│ │ └── client.ts # Claim HTTP client
│ └── cli/ # CLI (id.org.ai command)
│ ├── index.ts # Entry point + command router
│ ├── auth.ts # login/logout/whoami/token/status
│ ├── device.ts # Device authorization flow
│ ├── provision.ts # Provision command
│ ├── claim.ts # Claim command
│ └── storage.ts # Token storage (~/.id.org.ai/token)
├── packages/
│ └── react/ # @id.org.ai/react — React SDK
│ ├── src/
│ │ ├── provider.tsx # IdProvider (QueryClient + OAuth callback)
│ │ ├── hooks/ # useAuth(), useOrganizations()
│ │ ├── client.ts # HTTP client (session, orgs, widget-token)
│ │ └── pkce.ts # PKCE S256 challenge/verifier
│ └── test/ # 7 test suites (27 tests)
├── worker/ # Cloudflare Worker (Hono app, deployed to id.org.ai)
├── action/ # GitHub Action (dot-org-ai/id@v1)
├── site/ # Landing page (id.org.ai)
├── test/ # 29 test suites (1,296 tests, workerd pool)
├── test-e2e/ # E2E tests (7 suites, live endpoints)
└── package.json # npm: id.org.ai
Everything identity-related migrates from .org.ai/org.ai/ into this repo. The org.ai npm package continues to exist as the umbrella that re-exports id.org.ai alongside ~30 other .org.ai primitives (schema.org.ai, etc.).
| Source | Destination | Notes |
|---|---|---|
.org.ai/org.ai/src/do/Identity.ts | src/do/Identity.ts | Core IdentityDO — extend with claim/provision |
.org.ai/org.ai/src/db/schema.ts | src/db/schema.ts | All 12 identity tables — add claim fields |
.org.ai/org.ai/src/db/index.ts | src/db/index.ts | Re-exports |
.org.ai/org.ai/src/oauth/provider.ts | src/oauth/provider.ts | OAuth 2.1 provider |
.org.ai/org.ai/src/oauth/index.ts | src/oauth/index.ts | Re-exports |
.org.ai/org.ai/src/mcp/auth.ts | src/mcp/auth.ts | MCP authentication |
.org.ai/org.ai/src/mcp/index.ts | src/mcp/index.ts | Re-exports |
.org.ai/org.ai/src/auth/index.ts | src/auth/index.ts | Auth utilities |
.org.ai/org.ai/src/auth/stripe-connect.ts | src/auth/stripe-connect.ts | Stripe Connect |
.do/workers/workers/id.org.ai/src/index.ts | worker/index.ts | Worker entry point |
.do/workers/workers/id.org.ai/src/oauth-do.ts | worker/oauth-do.ts | OAuthDO |
.do/workers/workers/id.org.ai/wrangler.jsonc | worker/wrangler.jsonc | Worker config |
The org.ai npm package (.org.ai/org.ai/) is NOT being deprecated. It is the umbrella package that re-exports id.org.ai alongside schema.org.ai and approximately 30 other key .org.ai primitives. org.ai is the composition layer — id.org.ai is the identity-specific standard within it.
| File | Purpose |
|---|---|
src/github/app.ts | GitHub App webhook handler for push events |
src/github/action.ts | GitHub Action claim verification |
src/claim/index.ts | Claim orchestration (anonymous → claimed) |
src/claim/provision.ts | Sandbox tenant provisioning |
src/claim/verify.ts | Claim token verification |
action/action.yml | GitHub Action definition |
action/src/index.ts | GitHub Action runtime |
Anonymous tenants ARE production tenants — same Durable Object, same schema, same event log. The only differences are entity limits and integration access. Claiming a tenant is a metadata update, not a data migration. The Durable Object is the same before and after.
Expired anonymous tenants freeze — data preserved 30 days in R2 cold storage. The freeze response shows what the agent built: "47 contacts, 12 deals, 89 tasks." Sunk cost drives claiming.
try ToolExecute-with-rollback is architecturally clean with event sourcing: run the workflow, emit events to a temporary branch, show the agent exactly what would happen, then discard the branch. External integrations get stubbed mocks during try.
The MCP spec moved to CIMD (Client ID Metadata Documents) as the default. For anonymous onboarding, neither is needed at Level 0. At Level 2+, GitHub identity serves as the client identifier. DCR (POST /oauth2/register) is already implemented.
id.org.ai wraps WorkOS AuthKit for all human authentication. The custom AuthKit domain is id.org.ai. WorkOS handles SSO, social login, MFA, enterprise directory sync. id.org.ai adds the agent layer on top.
Consumer domains that live in the same Cloudflare account as id.org.ai can integrate without per-app Dynamic Client Registration. Account membership is the trust boundary.
A single canonical client_id — cid_trusted_account_v1 — is recognized at /oauth/authorize and /oauth/token for any redirect_uri whose host is in the TRUSTED_ACCOUNT_DOMAINS allowlist (worker env var, comma-separated bare hostnames). PKCE remains mandatory; scope and state validation are unchanged. There is no client_secret — it's a public client.
Implementation choice: the trusted-account client is fully synthesized from env config at request time. There is no client:cid_trusted_account_v1 row in the DCR store; the lookup is bypassed when the incoming client_id matches the canonical id. This avoids a one-time bootstrap step and means the allowlist is the single source of truth.
Onboarding a new in-account consumer:
TRUSTED_ACCOUNT_DOMAINS in worker/wrangler.jsonc.issuer = https://id.org.aiclient_id = cid_trusted_account_v1redirect_uri on a host matching the allowlistThat's it — no DCR call, no client_id paste, no env-var coordination. Removing a consumer is the inverse: remove its host from the allowlist and redeploy. Existing DCR'd clients (cid_* records in storage) continue to work unchanged for third-party consumers.
Trade-off: per-app revocation is coarser. Revoking the trusted-account client invalidates every in-account consumer at once. The intended granularity is per-domain via the allowlist.
See docs/adr/0007-trusted-account-oauth-via-better-auth.md for the full rationale.
_metaexplore and try toolsclaimToken, claimStatus, anonymousExpiresAt to identities schemadot-org-ai/id) — push webhook handlerdot-org-ai/id@v1) — OIDC claim confirmationPOST /api/claim, POST /api/provision, GET /api/tenant/:token~/.config/headlessly/agent.seed).headless.ly/agents/*.pub in gitdid:agent:ed25519:{base58pubkey}agent_keys, capability_tokens