NVIDIA / NVIDIA/NemoClaw

Design external-component requirements for declarative configuration and export

Open
#11,453 3 comments 0 reactions 0 assignees View on GitHub
needs: design
Dominant language
TypeScript
Stars
22.5k
Forks
3.1k
Avg merge
1d 43m
Merged PRs (30d)
718

Description

## Decision requested

@apurvvkumaria: please review the investigation and questions below and record the design decision, accepted scope, accountable maintainer, and validation expectations.

Parent: #10904. Interface dependency: #11340 / #11366.

**Decision: pending.** This issue requests design direction; it does not authorize implementation. Lifecycle-hook alignment, delivery of #11366, and APF/ATGW runtime qualification are handled separately.

## Problem Statement

The declarative configuration work needs to preserve a deployment's requirement for a registered external component. APF/ATGW is the motivating consumer.

The exporter can represent a verified effective policy, but that policy does not identify the external component required by the deployment. Copying the current host registration would also be insufficient: a component installed today might not have participated in an older sandbox's creation.

We need to define what configuration promises, which evidence establishes that promise, and how the contract preserves the ownership boundaries accepted in #11340 and #10514.

## Investigation findings

Source inspection used main `3e6fabc8fc1bcec0b58867c23733d9ca8c44a508` and the unmerged #11366 candidate `cfcc60b17a36cd2ae62144359c0e3a1ab5bbcd1e`. These are code-based findings, not a reproduced APF/ATGW export failure. A particular integration might already be rejected by another unsupported-setting check.

1. **The exporter has no external-component observation or representation.** Its gateway schema contains management, name, and port. The snapshot reader observes registry, gateway binding, sandbox identity, inference, and policy; it does not read component registration or activation state. The builder emits the effective policy as `network.policy.explicit`. [Schema](https://github.com/NVIDIA/NemoClaw/blob/3e6fabc8fc1bcec0b58867c23733d9ca8c44a508/src/lib/config/model.ts#L222), [snapshot reader](https://github.com/NVIDIA/NemoClaw/blob/3e6fabc8fc1bcec0b58867c23733d9ca8c44a508/src/lib/adapters/config/live-export-source.ts#L280), [builder](https://github.com/NVIDIA/NemoClaw/blob/3e6fabc8fc1bcec0b58867c23733d9ca8c44a508/src/lib/domain/config/export-document.ts#L60).
2. **The lifecycle candidate clears activation evidence after success.** Failed or ambiguous activation remains in the onboarding session. Successful activation clears that operation-local evidence. Its gateway identity hashes the component ID and interceptor socket path, which does not establish that a particular sandbox completed activation. [Finalization](https://github.com/NVIDIA/NemoClaw/blob/cfcc60b17a36cd2ae62144359c0e3a1ab5bbcd1e/src/lib/onboard/machine/handlers/finalization.ts#L208), [gateway identity](https://github.com/NVIDIA/NemoClaw/blob/cfcc60b17a36cd2ae62144359c0e3a1ab5bbcd1e/src/lib/onboard/docker-driver-gateway-config.ts#L127).
3. **The epic's earlier APF selector describes a different operation.** The proposed sandbox-level `network.interceptors: [{ type: apf }]` describes providerless, policyless creation. #11340 configures a gateway-level component with post-create activation. The candidate rejects combining registered-component onboarding with the existing APF selection. These paths must not be treated as interchangeable. [Epic design](https://github.com/NVIDIA/NemoClaw/issues/10904#issuecomment-5519192797), [candidate behavior](https://github.com/NVIDIA/NemoClaw/blob/cfcc60b17a36cd2ae62144359c0e3a1ab5bbcd1e/src/lib/onboard/external-component/onboarding.ts#L16).
4. **A component ID does not identify its full service configuration.** The accepted registration contains only `schemaVersion`, `componentId`, `interceptorSocketPath`, and `activationSocketPath`. It has no APF bundle or ATGW catalog version. The same ID on another host can refer to a differently configured service. [Accepted declaration](https://github.com/NVIDIA/NemoClaw/issues/11340).

## Questions for decision

The recommendations below are proposals, not accepted requirements.

### 1. What should the exported configuration promise?

Should it preserve only the requirement for an operator-registered component, or reproduce a particular APF/ATGW configuration?

**Recommendation:** Start with the component requirement. Keep service configuration with its existing owner. If reproducibility requires an immutable component profile or bundle identity, define that component-owned contract separately.

### 2. Where should component selection live?

Does one optional reference under `spec.gateway` match the gateway-wide interceptor and the accepted zero-or-one component limit? How should this coexist with the earlier sandbox-level APF selector?

**Recommendation:** Use a gateway-level reference and keep the existing providerless APF operation distinct. Match the existing declaration's `componentId`; do not introduce another registry.

Illustrative fragment only; the field name and syntax are undecided:

```yaml
spec:
gateway:
management: nemoclaw
name: nemoclaw
port: 8080
externalComponentRef: policy-governance
```

### 3. Which evidence is authoritative for export?

What proves that the source sandbox requires this component after successful activation evidence is cleared? Which existing owner should retain or expose that fact?

**Recommendation:** Consider minimal non-secret component-selection provenance bound to the existing sandbox identity, lifecycle generation, and gateway. Verify it against current gateway configuration. Preserve the requirement to remove operation-local activation evidence; do not retain a policy-ownership receipt or add a status endpoint merely to infer past activation.

Decide how to handle older sandboxes, late registration, removed or replaced components, and failed or ambiguous activation. Current registration alone must not be used to claim historical participation.

### 4. What does the exported policy mean with a component?

Should `network.policy.explicit` remain a verified snapshot? Before future apply support, will it mean initial policy, required entries, or some other bounded intent?

**Recommendation:** Preserve current OpenShell policy authority. A policy snapshot must not claim APF provenance or become a durable NemoClaw policy shadow. Legitimate live policy changes must not be rejected using an old locally retained hash.

### 5. What are reference, omission, and compatibility semantics?

When future config-driven onboarding names a component, must the protected registration match exactly? If the document omits a component while one is registered or active, what happens?

**Recommendation:** An explicit reference resolves through the existing protected registration. Omission selects no component. An incompatible active gateway causes a refusal before mutation; it must not be silently rewritten or disabled. Ambient registration must not override YAML intent.

Define compatibility behavior for ordinary onboarding, schema/protocol version handling, release target, migration diagnostics, and removal of any overlapping selection behavior before implementing the mutating slice.

### 6. What is the smallest supported export case?

Is one completed Linux/OpenClaw sandbox with supported hosted inference and one registered component a sufficient first case? Which agent, MCP, trust, or workload settings does the motivating integration additionally require?

**Recommendation:** Keep all existing export fidelity checks. A component reference must not make unrelated unsupported settings exportable or establish full ATGW recipe coverage. Identify any additional capability gaps explicitly.

## Desired Behavior

Subject to the design decision, an operator can export one supported completed sandbox without losing its verified external-component requirement.

For example, a sandbox whose retained selection and current gateway configuration agree on `policy-governance` exports that dependency alongside its existing supported settings. If the dependency cannot be established or represented, export refuses with a bounded diagnostic instead of guessing or silently omitting known required behavior.

A possible later slice honors the same reference through #10904's shared apply engine and #11340's lifecycle implementation.

## Scope and Exclusions

Included in this design decision:

- The public meaning and placement of the component requirement.
- The evidence required to export it accurately.
- Ownership of host registration, component configuration, and retained selection state.
- Failure, compatibility, policy, and validation expectations.
- The smallest complete export capability and its later apply dependency.

Excluded:

- Resolving the integration README's lifecycle-hook mismatch.
- Delivering or qualifying #11366.
- Installing, configuring, or supervising APF/ATGW services.
- New CA handoffs, credential resolvers, generic shell hooks, or provider-attachment APIs.
- Automatic activation retries or recovery; #11391 owns recovery design.
- Multiple components, broader topology support, or full enterprise configuration reproduction without separate acceptance.

## Ongoing Ownership

Proposed accountable maintainer for the configuration work: `cv`, subject to the decision requested above. No implementation owner is assigned by this issue.

NemoClaw configuration and onboarding maintainers own the schema, exporter, gateway writer, and shared engine. External-component maintainers own registration endpoints, service configuration, credentials, and activation behavior. OpenShell remains the authority for sandbox identity and effective policy.

## Placement and Support Expectations

Requested placement: core NemoClaw, as a child of #10904 consuming the generic interface in #11340.

The first proposed capability preserves a dependency on a registered component. It does not make the external services a NemoClaw-managed product surface or assert current component health.

[#10904's Accept decision](https://github.com/NVIDIA/NemoClaw/issues/10904#issuecomment-5529712248) and #11340 establish the surrounding architecture. This child needs its own accepted scope before implementation.

## Validation Plan

Use the existing schema, snapshot reader, stable-observation, verifier, builder, export-action, and publication tests. Add a lifecycle/state test only where the accepted provenance decision requires one. Regenerate the public schema from its source and retain its package contract.

| Source or operation | Proposed acceptance result |
|---|---|
| Completed supported sandbox, matching provenance and gateway component | Export one component reference with the supported configuration. |
| Ordinary OpenClaw or Hermes source without a component | Preserve existing canonical output. |
| Registration installed after the source sandbox was created | Do not infer component participation from registration alone. |
| Known dependency with missing provenance or wrong registration | Refuse without YAML or a success result. |
| Component removed/replaced or sandbox identity/generation changed | Report missing provenance or drift; do not guess. |
| Registration or gateway changes between observations | Apply the existing bounded read-observation policy; refuse if still unstable. |
| Failed or ambiguous activation | Preserve incomplete state; do not activate, retry, recover, or export a completed deployment. |
| Legitimate live policy change after activation | Read current OpenShell policy; do not consult an obsolete local policy receipt. |
| Unsupported MCP, trust, or workload settings | Preserve existing refusal until their separate capability is accepted. |
| Output failure | Preserve existing destination and temporary-file cleanup semantics. |
| Future apply with missing/wrong registration or conflicting gateway | Stop before gateway effects; do not silently select or disable a component. |

Use a generic component and synthetic credentials for deterministic evidence. Keep credentials out of YAML, diagnostics, events, arguments, and result JSON. Runtime qualification is separately owned; do not add a duplicate live matrix.

## Compatibility Requirements

Proposed initial boundary: one supported completed managed OpenClaw sandbox on Linux, supported hosted inference, and one component admitted through the accepted lifecycle contract. Confirm this boundary in question 6.

Keep ordinary OpenClaw/Hermes exports unchanged. File and stdout output use the same source-verification rules. Do not imply new resume, rebuild, recreation, multi-sandbox activation, or externally supervised gateway support.

## Security or Privacy Impact

The design must preserve protected-file validation, effective-user authorization, immutable sandbox identity, bounded diagnostics, and source stability.

Component credentials and CA/listener private keys remain in component-owned protected storage. Only the component accesses them; the component owns their lifetime, rotation, and removal. Export must not read or remove them. Public trust certificates are distinct from private keys.

Any retained selection provenance must not include policy ownership, policy contents, old policy hashes, activation bodies, or credentials. No new downloads, cryptography, arbitrary commands, or component mutations are proposed.

## Implementation Idea

After acceptance, deliver one complete export slice: representation, authoritative evidence, verification, serialization, refusal, tests, and owning guidance.

Reuse the existing export pipeline and lifecycle/state owners. A schema field without a successful exporter does not count as coverage.

If successful export cannot yet establish provenance, a separately bounded preliminary fix may refuse sources with detected component involvement. Such a refusal must state its detection limits and must not count as successful export coverage.

Later config-driven onboarding must consume the same representation and lifecycle engine after its compatibility and mutation contracts are accepted.

## Related Work

- #10904 — parent configuration epic.
- #11340 / #11366 — external-component lifecycle interface and implementation.
- #10514 — OpenShell policy authority.
- #11391 — incomplete-activation recovery.
- #11375 — lifecycle-interface documentation.

## Category

Feature

## Checklist

- [x] Searched related issues, PRs, and the epic's sub-issues; no existing component-export design issue was found.
- [x] Recorded the investigation, proposed outcome, evidence, and unresolved questions.
- [ ] Record the child-specific design decision before implementation.

Contributor guide

Open the contributing guide

Research direction

Read src/lib/config/model.ts, src/lib/adapters/config/live-export-source.ts, src/lib/domain/config/export-document.ts, and the linked lifecycle files to understand the current schema, observations, and activation state. Then review the existing schema, snapshot, verifier, builder, export-action, and publication tests. Done means recording an accepted component contract, evidence and ownership boundaries, compatibility rules, and validation expectations before implementation.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
backend-api-design, tooling
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.