Repository creation and CLI implementation roadmap
Date: 2026-08-20
Status: Implementation complete; the exact localhost:4000 cross-repository
loopback suite passes. The staging receipt remains gated.
Outcome
Implement repository creation, one-time GitHub import, Git smart HTTP, browser
management, and the @openagentsinc/cli package as one tested product across
the openagents.com Phoenix repository and the openagents Effect monorepo.
The product specification remains the contract: Repository creation, GitHub import, and OpenAgents CLI specification. This roadmap records implementation order, owning files, dependencies, tests, and release evidence. Update the status ledger as each work packet lands.
Recorded decisions
- Publish the npm package as
@openagentsinc/cli. - Expose the
openagentsbinary. Do not ship anoaalias in the first release. - Use Effect TypeScript and the monorepo-pinned Effect 4 release.
- Use
effect/unstable/clifor argument and flag parsing. - Default to the
productionprofile athttps://openagents.com. - Provide the
stagingprofile athttps://staging.openagents.com. - Provide the
localprofile athttp://localhost:4000. - Support
--api-url,OPENAGENTS_API_URL,--profile, andOPENAGENTS_PROFILEfor explicit endpoint selection. - Scope stored credentials to the normalized API origin.
- Pin automated and local end-to-end tests to
http://localhost:4000and fail closed if a test resolves a production or staging origin. - Use GitHub numeric user and organization IDs as namespace identity. Use the current GitHub login as a mutable display and route projection.
- Request
read:orgin addition to the existingrepogrant so OpenAgents can project organization membership and roles. - Import one accepted GitHub ref snapshot. Do not install a webhook or schedule later synchronization.
- Use
/{owner}/{repo}for the repository home after executable reserved-route tests prove that product routes cannot become namespaces. - Start distribution through npm. Gate standalone artifacts and an installer as a later release packet.
Definition of done
All of these statements require direct evidence before this roadmap can move to
Complete:
- A GitHub-authenticated user receives a user namespace keyed by the same numeric GitHub user ID.
- An eligible GitHub organization appears as a namespace keyed by the same numeric GitHub organization ID and current login.
- The browser and CLI create private or public repositories through the same Phoenix context operation.
- The browser and CLI import an authorized GitHub repository once, including its accepted branch and tag tips and depth-1 Git objects.
- A later GitHub update does not change the imported OpenAgents repository.
- The repository API returns stable JSON and error envelopes from a versioned Phoenix-owned contract artifact.
- Public repositories support anonymous clone and fetch.
- Private repositories remain hidden from unrelated users.
- Repository members with write roles can push. Read-only and unrelated users cannot push.
- Git storage uses a stable repository UUID and survives deletion of the local bare cache through WAL reconstruction.
@openagentsinc/clitargets production by default and can explicitly target staging, local, or a validated custom HTTPS API origin.- CLI credentials, GitHub credentials, device codes, and clone URLs never appear in command arguments, logs, JSON output, repository configuration, or durable import records.
mix precommitpasses inopenagents.com.pnpm run checkpasses inopenagents.- A disposable local test at
http://localhost:4000proves create, push, clone, exact commit SHA, import, exact refs, and no later synchronization.
Implementation dependency graph
flowchart TD
A["Contract and invariants"] --> B["Database authority"]
B --> C["GitHub namespace projection"]
B --> D["Repository API"]
C --> D
D --> E["Provisioning and Git HTTP"]
C --> F["One-time GitHub importer"]
E --> F
D --> G["CLI contract artifact"]
G --> H["Effect CLI"]
D --> I["Browser repository UI"]
F --> I
F --> J["Local end-to-end proof"]
H --> J
I --> J
The schema, migrations, route table, generated contract artifact, package manifest, lockfile, and behavior-contract registry are shared integration points. Change them serially under one integration owner.
Work packet 0: Record the contract and safety boundaries
Owner: openagents.com, with a matching invariant and behavior-contract
update in openagents when the CLI package begins.
- Update
docs/repository-creation-and-openagents-cli-spec.mdwith the package name and endpoint profiles. - Add this roadmap and keep its status ledger current.
- Add repository lifecycle, namespace, import snapshot, and credential
boundaries to
openagents.com/INVARIANTS.mdbefore server activation. - Add a pending then enforced CLI behavior contract in the monorepo for the user requirement that the CLI targets production by default and supports local, staging, and custom API origins.
- Record the
@openagentsinc/cliclaim and worktree in the accepted work packet before monorepo mutation.
Evidence: Documentation checks, invariant tests, behavior-contract tests, and a clean diff review that finds no production claim ahead of implementation.
Work packet 1: Add namespace and repository lifecycle persistence
Owner: openagents.com.
Generate migrations with mix ecto.gen.migration. Do not hand-author migration
timestamps.
- Add
namespaceswith provider identity, current slug, namespace kind, refresh time, state, and optional local user owner. - Add
namespace_aliasesfor previous GitHub logins. Allow aliases to resolve routes, but never use them as mutation authority. - Backfill a namespace for
OpenAgentsInc/openagents.comusing an operator- supplied or migration-safe GitHub organization ID. Refuse deployment if the required production identity is absent or inconsistent. - Add
namespace_id,description,lifecycle_state,provisioning_kind,provision_error_code,storage_key,created_by_user_id, andready_attorepositories. - Replace path uniqueness with
{namespace_id, name_key}while retaining a bounded compatibility projection forownerduring the migration. - Add
repository_importswith immutable source IDs, bounded source projections, accepted ref digest, head SHA, state, attempts, error code, and timing. - Add
repository_provisioning_outboxwith operation kind, repository ID, import ID, idempotency identity, attempt state, retry time, and bounded failure code. - Add a request-idempotency table keyed by principal, operation, key, and normalized request digest.
- Add Ecto schemas under
lib/openagents/repositories/and associations onRepository. - Rework
OpenAgents.Repositoriesaround transactionally created repository, owner membership, optional import, idempotency receipt, and outbox rows.
Tests: test/openagents/repositories_test.exs, migration lineage tests,
constraint tests, rename/alias tests, collision tests, atomic rollback tests,
and migration up/down rehearsal against populated fixtures.
Work packet 2: Project GitHub namespaces and import sources
Owner: openagents.com.
- Extend
OpenAgents.GitHubwith bounded Req adapters for:- the authenticated user,
- active organization memberships,
- one repository by
owner/name, - paginated repositories available to the user,
- repository permissions,
- branch and tag refs,
- Git LFS detection inputs.
- Decode provider responses into internal structs. Do not pass raw provider maps into contexts or LiveViews.
- Add a namespace projection service that upserts the user namespace at GitHub sign-in and refreshes organization namespaces before organization writes.
- Treat GitHub numeric IDs as authority and logins as mutable projections.
- Require an active organization membership and the first-release
admincreate policy before an organization destination mutation. - Require source read access for import. Do not require source-repository admin access merely to make a one-time copy.
- Add
read:orgto the OAuth request and exact granted-scope validation. - Make existing connected users reconnect when their retained grant lacks a required scope. Do not rewrite stored scope metadata.
- Return stable failures such as
github_connection_required,github_scope_required,namespace_not_allowed, andsource_repository_not_accessible.
Tests: Req fakes for pagination, public and private repositories, renamed logins, private organization membership, stale membership, missing scope, provider failure, rate limiting, malformed JSON, and token redaction.
Work packet 3: Implement the repository REST API
Owner: openagents.com.
Add thin controllers and keep policy in OpenAgents.Repositories services.
- Add authenticated routes:
POST /api/v3/user/reposPOST /api/v3/orgs/{org}/reposPOST /api/v3/user/repos/importsPOST /api/v3/orgs/{org}/repos/importsGET /api/v3/user/reposGET /api/v3/repository-imports/{id}
- Add optional-auth
GET /api/v3/repos/{owner}/{repo}. - Add an optional bearer-token pipeline that permits anonymous public reads but authenticates a supplied PAT before private reads.
- Add explicit route-authority entries for authenticated
GETroutes because the current classifier treats/api/v3reads as public. - Enforce
forge:write, user status, namespace authority, visibility, lifecycle state, quotas, names, branches, and idempotency before persistence. - Return
201 Createdwhen bounded provisioning finishes and202 Acceptedwhen durable work continues. - Return stable error envelopes and conceal private repositories with
404. - Add opaque cursor pagination with a maximum page size of 100.
- Build JSON projections in
RepositoryJSONandRepositoryImportJSON; do not assemble public JSON in context modules. - Add a versioned repository API artifact under
priv/api-contracts/and an authenticated-independent route or build task that exposes its exact bytes.
Tests: New controller tests for status, shape, policy, private concealment,
pagination, idempotency, conflict, organization refresh, imported source
validation, 201/202, and every stable error code. Extend
test/openagents_web/route_authority_test.exs.
Work packet 4: Make repository provisioning durable
Owner: openagents.com.
- Add an OTP provisioner under
OpenAgents.Repositories.Provisionerand start it through the application supervision tree withstart_supervised!/1in tests. - Claim outbox rows with database locking, bounded attempts, and retry times.
- Create an empty WAL index using
repository.storage_keybefore declaring a repository ready. - Change
OpenAgents.Forge.Repos,WAL,Sync,Pushes,Browse, and Git HTTP resolution to use stable repository storage keys instead of the process-wide repository-name allowlist. - Keep the deployable repository allowlist separate. Creating a repository must never make it buildable or deployable.
- Make each provisioning transition idempotent and crash-recoverable.
- Bound and redact operational errors before persistence or response.
- Add a recovery scan for stranded
provisioningand retryablefailedrecords.
Tests: Crash after each transition, duplicate outbox delivery, CAS conflict, cache deletion and reconstruction, two same-named repositories in different namespaces, storage-key path containment, and proof that repository creation does not change deployment targets.
Work packet 5: Implement one-time GitHub import
Owner: openagents.com.
- Resolve and persist the immutable GitHub source repository and owner IDs, default branch, permissions, branch and tag map, ref digest, and default head before the database transaction.
- Fetch the accepted refs at depth 1 into a unique temporary bare repository.
- Supply the retained GitHub token through a server-owned Git credential callback or askpass boundary. Never place it in a URL, argv, environment dump, Git config, log, or import record.
- Verify that the fetched refs match the accepted digest. Fail with a stable source-change code if the snapshot cannot be reproduced.
- Convert the imported objects, shallow boundaries, and refs into the destination WAL and materialize the destination cache.
- Set the symbolic default branch, accepted head SHA, import completion time, and repository readiness atomically at the final database transition.
- Remove temporary workspaces after success, expected failure, interruption, or recovery cleanup.
- Detect LFS pointer use and return the required pointer-only warning.
- Install no webhook and schedule no later provider read or write.
Tests: Public and private source fixtures, multiple branches and annotated tags, empty source, submodule pointers, LFS pointers, source changes during acceptance, interruption, retry, cleanup, exact ref digest, later source update, and assertions that neither side receives a synchronization call.
Work packet 6: Authorize Git smart HTTP by repository
Owner: openagents.com.
- Use the canonical
/{owner}/{repo}.gitroute while keeping the temporary/git/openagents.com.gitcompatibility route required by the forge cutover contract. - Allow anonymous upload-pack only for a ready public repository.
- Accept
oa_pat_...through HTTP Basic password input for authenticated Git operations and resolve it to a user principal. - Check repository membership and role before private upload-pack or any receive-pack operation.
- Preserve paired-computer and operator credentials only for their documented operational lanes. Do not let them bypass repository resolution.
- Return indistinguishable
404responses for private or missing repository reads where concealment applies. - Keep request bodies bounded, argv-only Git invocation, WAL persistence before push acknowledgment, and exact rollback on WAL failure.
Tests: Anonymous public clone, anonymous private refusal, member private clone, writer push, viewer refusal, unrelated-user refusal, banned-user refusal, failed/provisioning repository refusal, compatibility route, protocol v2, and credential-redaction scans.
Work packet 7: Add CLI device authorization
Owner: openagents.com server contract and browser UI.
- Add digested, expiring device authorization records with one-time claim and polling limits.
- Add public create and poll endpoints for a secret device code.
- Add an authenticated, CSRF-protected browser approval page.
- Mint one scoped
oa_pat_...after approval and return its plaintext exactly once. - Return stable pending, slow-down, denied, expired, claimed, and approved states without enabling enumeration.
- Add
cache-control: no-storeon every authorization response.
Tests: expiry, denial, one-time delivery, polling pace, collision, CSRF, revoked user, banned user, concurrent claims, token digest storage, and log redaction.
Work packet 8: Build the repository browser interface
Owner: openagents.com.
- Replace the hard-coded repository card with a scoped repository stream.
- Add authenticated repository list, empty, pagination, provisioning, failed, and ready states.
- Add
/repositories/newwith GitHub user and eligible organization namespace selection, name, description, visibility, and default branch. - Add
/repositories/import/githubwith a paginated GitHub repository picker, destination name, matching namespace, visibility, LFS warning, and explicit one-time import copy. - Add
/{owner}/{repo}repository home, clone controls, import receipt, and links to code, Issues, and Projects. - Put the dynamic repository route after every reserved route and maintain an executable reserved-segment inventory.
- Use
OpenAgentsWeb.UIprimitives, Basecoat imports already required by the surface, stable DOM IDs, keyboard operation, and responsive layouts. - Keep GitHub tokens and raw Git output outside LiveView assigns.
Tests: LiveView forms and outcomes by DOM ID, namespace selection, private default, import picker pagination, import progress/failure, ready-only clone instructions, reserved routes, accessibility, and browser smoke coverage.
Work packet 9: Scaffold @openagentsinc/cli
Owner: openagents monorepo in a fresh worktree from current
origin/main.
- Create
packages/openagents-cli/package.jsonwith name@openagentsinc/cli, ESM exports,openagentsbin, Node 24 engine, build, test, typecheck, lint, and package verification scripts. - Add
tsconfig.jsonusing the monorepo TypeScript and Effect language service conventions. - Add the package to the existing workspace through
packages/*; do not add a second workspace mechanism. - Pin
effect,@effect/platform-node, and test dependencies through the root catalog. Update the shared lockfile once under the integration owner. - Add Effect Schema decoders for the Phoenix-owned contract artifact and pin its version and SHA-256 digest.
- Define services for configuration, credentials, HTTP, authentication, repository operations, Git, credential helper, browser launch, and output.
- Model expected failures with
Schema.TaggedErrorClassand map exit codes in one exhaustive boundary. - Add the owner-stated endpoint behavior to the package behavior-contract registry and enforce it with tests.
Tests: package entrypoint, --help, --version, invalid input, contract
digest, schema decoding, packaging contents, Node 24 execution, and no
production network access from tests.
Work packet 10: Implement CLI configuration and authentication
Owner: openagents.
- Resolve configuration in this order: command flags, environment variables, persisted profile, then production default.
- Validate and normalize API origins. Permit plain HTTP only on loopback hosts.
- Keep credentials isolated by normalized origin.
- Use
ConfigandConfigProviderfor environment input; do not readprocess.envin application services. - Implement
auth login, browser launch, device polling withSchedule, token stdin, status, logout, and Git helper setup. - Use an admitted operating-system credential adapter for attended use. Use
OPENAGENTS_TOKENwithout persistence for headless use. - Implement the exact Git credential-helper protocol without printing the token.
- Redact authorization headers, tokens, device secrets, filesystem paths, and raw response bodies from every output mode.
Tests: production, staging, local, custom HTTPS, loopback HTTP, precedence, origin-scoped credentials, malformed origins, fake browser, fake clock polling, headless behavior, token stdin, JSON output, signals, and secret tripwires.
Work packet 11: Implement CLI repository commands
Owner: openagents.
- Implement
repo create, including visibility, description, branch, source directory, remote name, idempotency key,201/202, and polling. - Implement
repo import, including matching namespace, destination name, visibility, timeout, source head receipt, and no-sync notice. - Implement cursor-based
repo listandrepo view. - Implement
repo cloneusing the server-provided clone URL. - Implement owner-only
repo deletewith explicit confirmation and storage cleanup. - Implement safe repository inference from an admitted remote and explicit
-Roverride. - Refuse to overwrite an existing unrelated remote.
- Execute Git with argv arrays, bounded captured output, cancellation, and no credential in the remote URL.
- Keep human progress on stderr when JSON owns stdout.
Tests: all command options, mutual exclusions, error and exit-code mapping, idempotent retry, timeout without server cancellation, remote inference, remote collision, Git failure, JSON snapshots, interruption, and token redaction.
Work packet 12: Verify locally across both repositories
Owner: cross-repository integration.
- Start an isolated Phoenix server at
http://localhost:4000with local WAL storage, a disposable database, deterministic GitHub fakes, and forge deployment disabled. - Create a fixture GitHub user, organization, retained grant, and source bare repository without exposing a token to the test process output.
- Run the CLI with
OPENAGENTS_API_URL=http://localhost:4000. - Authenticate with a disposable PAT or complete the device flow.
- Create a repository, configure Git credentials, push a commit, clone it, and compare the exact commit SHA.
- Import a fixture with multiple branches and tags, compare the complete ref map, update the source, and prove the destination remains unchanged.
- Prove anonymous public clone, private concealment, writer push, and viewer refusal.
- Delete the destination bare cache, reconstruct it from WAL, clone again, and compare refs.
- Scan server and CLI logs plus Git config for fixture secrets and credentialed URLs.
- Run
mix precommitandpnpm run checkfrom the exact delivered revisions.
Evidence: Store a bounded test receipt with repository revisions, contract digest, API origin, exact commit and ref digests, test counts, and secret-scan result. Do not store tokens, local absolute paths, or repository content.
Work packet 13: Stage and release
Owner: release operator after local completion.
- Deploy the server to
https://staging.openagents.comthrough the admitted staging gate. - Run the CLI with
--profile stagingand repeat create, import, clone, push, refusal, recovery, and redaction checks. - Confirm migrations, OAuth reconnect copy, GitHub rate behavior, Cloud Storage WAL durability, and private repository concealment.
- Pack
@openagentsinc/cli, inspect the tarball, install it into an empty prefix, and run its command matrix. - Publish an npm preview only after the server and CLI contract digests match.
- Keep standalone binaries, the installer, self-update, pull requests, mirroring, deletion, and SSH transport in later gated packets.
Status ledger
| Packet | State | Evidence |
|---|---|---|
| 0. Contract and safety boundaries | Complete | INVARIANTS.md, Phoenix contract artifact, CLI behavior contract |
| 1. Namespace and lifecycle persistence | Complete | Lifecycle migrations and repository_lifecycle_test.exs |
| 2. GitHub namespace projection | Complete | GitHub adapter, exact repo and read:org scopes, projection tests |
| 3. Repository REST API | Complete | Repository controllers, JSON contract, namespace quota, idempotency, and pagination tests |
| 4. Durable provisioning | Complete | Provisioning outbox, reclaimable worker, bounded import timeout, crash-workspace recovery, audit events, and cache reconstruction tests |
| 5. One-time GitHub import | Complete | Frozen refs, depth-1 Git bundle WAL entry, preserved shallow boundaries, cache-loss, and no-later-sync tests |
| 6. Repository Git HTTP authorization | Complete | Public reads, PAT writes, token reauthentication, role refusal, explicit computer grants, audited writes, and legacy-route tests |
| 7. CLI device authorization | Complete | One-time device-code context, API, browser approval, and polling tests |
| 8. Repository browser interface | Complete | Paginated list, create, import, empty, failed, private, and code-route LiveView tests |
| 9. CLI package scaffold | Complete | @openagentsinc/cli, Effect 4 command graph, build, and package inspection |
| 10. CLI configuration and authentication | Complete | Profiles, persisted configuration precedence, custom origins, OS credential store, headless refusal, stable errors, and origin-isolated Git helper tests |
| 11. CLI repository commands | Complete | Create, matching-namespace import, idempotent transport retry, cursor list, view, clone, source remote, inference, signal cancellation, and refusal tests |
| 12. Local cross-repository verification | Complete | The disposable suite passes on exact http://localhost:4000 for create, push, clone, anonymous read, private concealment, viewer push refusal, cache reconstruction, exact import refs, and no later sync. See f8a7822-5bd8fb1eaf.json. |
| 13. Staging and release | Not started | — |
Completion audit
Before changing this roadmap to Complete, inspect current files and command
output for every definition-of-done item. A passing unit test does not prove an
end-to-end behavior unless the test crosses the same browser or CLI, API,
database, GitHub adapter, WAL, and Git boundaries as the requirement. Record
missing or indirect evidence as incomplete and continue implementation.