Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-08-23
55 changes: 55 additions & 0 deletions openspec/changes/archive/2026-08-23-add-namecom-api-tool/design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
## Context

The madz harness uses a tool-based architecture where each tool is a plain async function with a Zod input schema, registered in `src/tools/index.js`. Action-based tools (like `email` and `process`) use a single tool with an `action` enum parameter that dispatches to handler functions. The name.com API is a RESTful API with 72 operations across 17 tag groups, using Basic Auth with username:token, rate-limited to 20 requests/second.

## Goals / Non-Goals

**Goals:**
- Single `namecom` tool wrapping all 72 name.com Core API operations
- Action-based dispatch pattern matching existing tools
- Basic Auth via `NAMECOM_USERNAME` and `NAMECOM_TOKEN` env vars
- URL allowlist validation for outbound requests
- Consistent error handling for API errors (401, 403, 429, 500, 502, 503, 504)
- Full test coverage across all 17 tag groups

**Non-Goals:**
- OAuth authentication flows
- Caching layer for API responses
- Request queue/bulk operation throttling (rate limit is 20 req/s, generous for most use cases)
- Domain parking or transfer-out flows not covered by the API spec

## Decisions

### Decision 1: Single tool with action enum vs. separate tools per tag group
**Choice:** Single tool with `action` parameter.
**Rationale:** 17+ separate tools would bloat the tool surface. The `email` and `process` tools demonstrate this pattern works well. The LLM can reason about a single tool with 40+ actions more effectively than 17 separate tools.
**Alternatives considered:** Separate tools per tag group (rejected — too many tools, fragmented tool surface).

### Decision 2: Zod schema design — flat optional fields vs. params record
**Choice:** Common parameters as optional fields (`domainName`, `perPage`, `page`, `type`, `name`, `value`, `ttl`), action-specific parameters via a flexible `params` record.
**Rationale:** The API has 72 operations with varying parameters. A flat schema with 100+ optional fields is unwieldy. A `params` record keeps the schema manageable while still providing type safety for common parameters.
**Alternatives considered:** Flat schema with all parameters as optional fields (rejected — too large, hard to maintain).

### Decision 3: Native fetch vs. HTTP library
**Choice:** Native `fetch()` (Node.js 24+).
**Rationale:** No external dependencies needed. The API is simple REST — no need for axios or node-fetch. Basic Auth is trivial with `fetch` headers.
**Alternatives considered:** axios (rejected — adds dependency for no benefit).

### Decision 4: URL allowlist enforcement
**Choice:** Hardcoded allowlist of `api.name.com` and `api.dev.name.com` in the HTTP client.
**Rationale:** OWASP compliance — prevents SSRF via user-controlled URLs. The API base URL is fixed, so a hardcoded allowlist is appropriate.
**Alternatives considered:** Configurable base URL (rejected — unnecessary flexibility, security risk).

## Risks / Trade-offs

- **Rate limiting:** 20 req/s limit means bulk operations need throttling. Mitigation: Document the limit in the tool description, return guidance on 429 responses. Full queue implementation deferred.
- **Large Zod schema:** 40+ actions with varying parameters. Mitigation: `params` record for action-specific fields, common parameters as optional fields.
- **Error handling:** API returns varying response shapes for different error codes. Mitigation: Consistent error wrapper in `makeRequest()` that normalizes all errors to `{ ok: false, error: string }`.

## Migration Plan

No migration needed — this is a greenfield feature. The tool is registered alongside existing tools and requires no config.yaml changes.

## Open Questions

- None. The action map, auth design, and schema approach are defined by the issue specification.
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
## Why

Users need to manage domains, DNS records, transfers, and related services through name.com's API. Currently there is no tool for this in the harness. A single unified tool with an `action` parameter keeps the tool surface clean while providing full API coverage.

## What Changes

- Add a new `namecom` tool wrapping 72 name.com Core API operations across 17 tag groups
- Authentication via `NAMECOM_USERNAME` and `NAMECOM_TOKEN` environment variables (Basic Auth)
- Action-based dispatch pattern matching existing `email` and `process` tools
- HTTP client with URL allowlist validation, rate limit handling, and consistent error responses
- Register tool in `src/tools/index.js` with `network:outbound` permission

## Capabilities

### New Capabilities

- `namecom-api`: Full name.com Core API integration — domain management, DNS records, transfers, email/URL forwarding, vanity nameservers, DNSSEC, webhook notifications, orders, refunds, TLD pricing, premium domains, contact verification, and account info

### Modified Capabilities

- None

## Impact

- **Affected code**: `src/tools/index.js` (tool registration), new file `src/tools/namecom/index.js`
- **New dependencies**: None — uses native `fetch()` and existing Zod
- **Tests**: New file `tests/unit/tools/namecom.test.js`
- **Config**: No config.yaml changes — credentials from env vars only

## Non-goals

- OAuth authentication flows
- Reseller account management beyond what the API provides
- Domain parking or transfer-out flows not covered by the API spec
- Caching layer for API responses
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
## ADDED Requirements

### Requirement: Tool authentication
The system MUST authenticate all name.com API requests using Basic Auth with credentials from `NAMECOM_USERNAME` and `NAMECOM_TOKEN` environment variables. The system MUST reject requests when credentials are not configured.

#### Scenario: Authentication configured
- **WHEN** `NAMECOM_USERNAME` and `NAMECOM_TOKEN` are set in the environment
- **THEN** the tool includes `Authorization: Basic <base64(username:token)>` header on all API requests

#### Scenario: Authentication not configured
- **WHEN** `NAMECOM_USERNAME` or `NAMECOM_TOKEN` is not set
- **THEN** the tool returns `{ ok: false, error: "name.com credentials not configured" }` for all actions

### Requirement: URL allowlist validation
The system MUST restrict all outbound requests to `api.name.com` and `api.dev.name.com` only.

#### Scenario: Valid host
- **WHEN** the request target is `api.name.com` or `api.dev.name.com`
- **THEN** the request proceeds normally

#### Scenario: Invalid host
- **WHEN** the request target is not in the allowlist
- **THEN** the tool returns `{ ok: false, error: "Host not allowed" }`

### Requirement: Action dispatch
The system MUST route each `action` value to the correct API endpoint using a switch statement.

#### Scenario: Valid action
- **WHEN** the `action` field matches a known action (e.g., `listDomains`, `createRecord`)
- **THEN** the tool dispatches to the corresponding handler and makes the appropriate API request

#### Scenario: Unknown action
- **WHEN** the `action` field does not match any known action
- **THEN** the tool returns `{ ok: false, error: "Unknown action: ..." }`

### Requirement: Domain management actions
The system MUST support all 19 domain operations: listDomains, createDomain, getDomain, updateDomain, enableAutorenew, disableAutorenew, enableWhoisPrivacy, disableWhoisPrivacy, lockDomain, unlockDomain, renewDomain, setContacts, setNameservers, getAuthCode, getPricing, checkAvailability, searchDomains, zoneCheck, purchasePrivacy.

#### Scenario: List domains
- **WHEN** action is `listDomains` with optional `perPage` and `page` parameters
- **THEN** the tool calls `GET /core/v1/domains` and returns the domain list

#### Scenario: Create domain
- **WHEN** action is `createDomain` with domain registration parameters
- **THEN** the tool calls `POST /core/v1/domains` and returns the registration result

#### Scenario: Enable autorenew
- **WHEN** action is `enableAutorenew` with `domainName` parameter
- **THEN** the tool calls `POST /core/v1/domains/{domainName}:enableAutorenew` and returns success

### Requirement: DNS record management
The system MUST support all 5 DNS operations: listRecords, createRecord, getRecord, updateRecord, deleteRecord.

#### Scenario: List DNS records
- **WHEN** action is `listRecords` with `domainName` parameter
- **THEN** the tool calls `GET /core/v1/domains/{domainName}/records` and returns the record list

#### Scenario: Create DNS record
- **WHEN** action is `createRecord` with `domainName`, `type`, `name`, `value`, and `ttl` parameters
- **THEN** the tool calls `POST /core/v1/domains/{domainName}/records` and returns the created record

#### Scenario: Delete DNS record
- **WHEN** action is `deleteRecord` with `domainName` and `id` parameters
- **THEN** the tool calls `DELETE /core/v1/domains/{domainName}/records/{id}` and returns success

### Requirement: URL forwarding management
The system MUST support all 9 URL forwarding operations: listUrlForwardings, createUrlForwarding, getUrlForwarding, updateUrlForwarding, deleteUrlForwarding, listUrlForwardingsByDomain, getUrlForwardingById, updateUrlForwardingById, deleteUrlForwardingById.

#### Scenario: List URL forwardings
- **WHEN** action is `listUrlForwardings` with `domainName` parameter
- **THEN** the tool calls `GET /core/v1/domains/{domainName}/url/forwarding` and returns the forwarding list

### Requirement: Email forwarding management
The system MUST support all 5 email forwarding operations: listEmailForwardings, createEmailForwarding, getEmailForwarding, updateEmailForwarding, deleteEmailForwarding.

#### Scenario: Create email forwarding
- **WHEN** action is `createEmailForwarding` with `domainName` and forwarding parameters
- **THEN** the tool calls `POST /core/v1/domains/{domainName}/email/forwarding` and returns the created forwarding

### Requirement: Vanity nameserver management
The system MUST support all 5 vanity nameserver operations: listVanityNameservers, createVanityNameserver, getVanityNameserver, updateVanityNameserver, deleteVanityNameserver.

#### Scenario: List vanity nameservers
- **WHEN** action is `listVanityNameservers` with `domainName` parameter
- **THEN** the tool calls `GET /core/v1/domains/{domainName}/vanity_nameservers` and returns the list

### Requirement: DNSSEC management
The system MUST support all 4 DNSSEC operations: listDnssecs, createDnssec, getDnssec, deleteDnssec.

#### Scenario: List DNSSEC records
- **WHEN** action is `listDnssecs` with `domainName` parameter
- **THEN** the tool calls `GET /core/v1/domains/{domainName}/dnssec` and returns the DNSSEC list

### Requirement: Transfer management
The system MUST support all 7 transfer operations: listTransfers, createTransfer, getTransfer, cancelTransfer, cancelExternalTransferOut, createInternalTransferIn, getTransferEligibility.

#### Scenario: List transfers
- **WHEN** action is `listTransfers` with optional pagination parameters
- **THEN** the tool calls `GET /core/v1/transfers` and returns the transfer list

#### Scenario: Create transfer
- **WHEN** action is `createTransfer` with domain and auth code parameters
- **THEN** the tool calls `POST /core/v1/transfers` and returns the transfer result

### Requirement: Webhook notification management
The system MUST support all 4 webhook notification operations: listNotifications, subscribeNotification, getNotification, modifyNotification, deleteNotification.

#### Scenario: List notifications
- **WHEN** action is `listNotifications`
- **THEN** the tool calls `GET /core/v1/notifications` and returns the subscription list

### Requirement: Domain info operations
The system MUST support all 3 domain info operations: getTldRequirements, checkDomainClaims, getTldRequirementsV2.

#### Scenario: Check domain claims
- **WHEN** action is `checkDomainClaims` with `domain` parameter
- **THEN** the tool calls `POST /core/v1/domaininfo/claims/{domain}` and returns the claims result

### Requirement: Contact verification operations
The system MUST support all 3 contact verification operations: listUnverifiedContacts, verifyContact, resendContactVerification.

#### Scenario: List unverified contacts
- **WHEN** action is `listUnverifiedContacts`
- **THEN** the tool calls `GET /core/v1/contacts/unverified` and returns the unverified list

### Requirement: Orders operations
The system MUST support all 2 order operations: listOrders, getOrder.

#### Scenario: List orders
- **WHEN** action is `listOrders` with optional pagination parameters
- **THEN** the tool calls `GET /core/v1/orders` and returns the order list

### Requirement: Account info operations
The system MUST support the account balance operation: getAccountBalance.

#### Scenario: Get account balance
- **WHEN** action is `getAccountBalance`
- **THEN** the tool calls `GET /core/v1/accountinfo/balance` and returns the balance

### Requirement: Hello endpoint
The system MUST support the hello operation for health checking.

#### Scenario: Hello
- **WHEN** action is `hello`
- **THEN** the tool calls `GET /core/v1/hello` and returns the server time and version info

### Requirement: Refund operations
The system MUST support the refund operation: processRefund.

#### Scenario: Process refund
- **WHEN** action is `processRefund` with order item parameters
- **THEN** the tool calls `POST /core/v1/refund` and returns the refund result

### Requirement: TLD pricing operations
The system MUST support the TLD pricing operation: getTldPricing.

#### Scenario: Get TLD pricing
- **WHEN** action is `getTldPricing`
- **THEN** the tool calls `GET /core/v1/tldpricing` and returns the pricing list

### Requirement: Premium domains operations
The system MUST support the premium domains operation: getPremiumDomainsList.

#### Scenario: Get premium domains list
- **WHEN** action is `getPremiumDomainsList`
- **THEN** the tool calls `GET /core/v1/premiumdomainslist` and returns the premium list

### Requirement: Accounts operations
The system MUST support the account creation operation: createAccount.

#### Scenario: Create account
- **WHEN** action is `createAccount` with account parameters
- **THEN** the tool calls `POST /core/v1/accounts` and returns the created account details

### Requirement: Error handling
The system MUST handle API error responses consistently, returning `{ ok: false, error: string }` for all error cases.

#### Scenario: 401 Unauthorized
- **WHEN** the API returns 401
- **THEN** the tool returns `{ ok: false, error: "Authentication failed" }`

#### Scenario: 429 Rate Limit
- **WHEN** the API returns 429
- **THEN** the tool returns `{ ok: false, error: "Rate limit exceeded. Retry after <timestamp>" }`

#### Scenario: 503 Service Unavailable
- **WHEN** the API returns 503
- **THEN** the tool returns `{ ok: false, error: "Service unavailable. See https://status.name.com" }`

#### Scenario: Network error
- **WHEN** the HTTP request fails (timeout, connection refused)
- **THEN** the tool returns `{ ok: false, error: "Request failed: <message>" }`

### Requirement: Rate limit awareness
The system MUST parse the `X-RateLimit-Reset` header from 429 responses and include the retry timestamp in the error message.

#### Scenario: Rate limit with reset header
- **WHEN** the API returns 429 with `X-RateLimit-Reset` header
- **THEN** the error message includes the Unix timestamp for when the rate limit resets

### Requirement: Tool registration
The system MUST register the `namecom` tool in `src/tools/index.js` with `network:outbound` permission and appropriate agent classifications.

#### Scenario: Tool is registered
- **WHEN** the system starts
- **THEN** the `namecom` tool is available to agents with `network:outbound` permission

### Requirement: Zod schema validation
The system MUST validate all tool input against a Zod schema before dispatching to handlers.

#### Scenario: Missing required parameter
- **WHEN** a required parameter (e.g., `domainName` for domain actions) is missing
- **THEN** Zod validation rejects the input before the handler is called

### Requirement: HTTP client with timeout
The system MUST attach a timeout to all HTTP requests to prevent hanging.

#### Scenario: Request timeout
- **WHEN** an HTTP request exceeds the timeout (30 seconds)
- **THEN** the tool returns `{ ok: false, error: "Request timed out" }`
Loading
Loading