
Description
Build or migrate infra-controller REST API endpoints that call on-site NICo Core through the generic Core gRPC proxy. Use when working on REST-to-Core operations, ExecuteCoreGRPC, coreproxy, forge.Forge methods, creating new proxied REST endpoints, or migrating bespoke workflows to the gRPC proxy.
SKILL.md
REST Core gRPC Proxy Skill
Use this guidance when building or converting infra-controller REST API endpoints that need to call on-site NICo Core through the generic Core gRPC proxy.
Current Proxy Contract
- Cloud helper:
rest-api/api/pkg/api/handler/util/common/coreproxy.go,ExecuteCoreGRPC. - Shared contract:
rest-api/common/pkg/coreproxy/coreproxy.go, withcoreproxy.Requestandcoreproxy.Response. - Site workflow/activity:
InvokeCoreGRPCandInvokeCoreGRPCOnSite. - Site Core invocation:
CoreGrpcClient.InvokeJSON. - Temporal transport payload: protojson, so non-secret request fields and responses remain readable in Temporal UI.
- Secret transport payload: selected top-level protojson fields are redacted from
RequestJSONand carried separately inEncryptedSecrets. - Final site-to-Core call: normal binary gRPC. The JSON step is only the generic Temporal payload representation.
Before Coding
Confirm these details before editing:
- REST operation path, method, auth role, org/site scoping, request model, response model, and expected status code.
- Target Core method, usually
/forge.Forge/<Method>, and whether it is unary. The proxy does not support streaming methods. - Typed protobuf request and optional typed protobuf response.
- Secret fields that must not appear in Temporal history. These must be top-level protojson field names such as
password. - Whether the REST operation maps to one Core call or must compose multiple
calls to
ExecuteCoreGRPC. A single REST handler may invoke the proxy helper more than once when the API operation requires multiple Core gRPC calls. - Whether each Core operation is non-idempotent. The shared proxy workflow intentionally runs each activity once with no automatic retry.
Implementation Workflow
- Inspect the nearest existing REST handler and model patterns before editing.
- Add or update the API model with validation, REST-to-proto mapping, and response shaping. Keep API compatibility and OpenAPI required/nullable semantics aligned with server validation.
- Keep auth, tenant/org membership, site lookup, role checks, request validation, and REST semantics in the REST handler. The proxy is only the cloud-to-site transport.
- Build the typed protobuf request before calling the proxy. Prefer generated protobuf types over maps or ad hoc JSON.
- Call
common.ExecuteCoreGRPC(ctx, siteTemporalClient, fullMethod, reqProto, respProtoOrNil, siteIDSecretKey, secretFields...). - Pass the site ID string as the secret key when redacting fields for a site-scoped call; the site-agent decrypts with the same site key.
- Never log full request bodies when they can contain secrets. Log method, kind, site ID, or other non-secret metadata only.
- Return a curated REST response. Do not expose Core protobufs or secret fields directly unless the API contract already does.
- For a new public REST endpoint, register the route, update
rest-api/openapi/spec.yaml, and regenerate SDK files if the repo workflow requires it. For an existing REST endpoint being migrated from a bespoke workflow to the generic proxy, keep the REST contract unchanged and do not touch OpenAPI or generated SDK files unless the public API actually changes.
Tests To Add
- Model validation for required fields, enums, conditional requirements, and REST-to-proto mapping.
- Handler tests for auth/site validation, request normalization,
ExecuteCoreGRPCinvocation arguments, secret field names, status code, and password-free response. - Route registration tests.
- OpenAPI/schema checks and generated SDK checks only for new endpoints or public API changes. Pure migrations from bespoke workflows to the generic proxy should not change the REST contract, OpenAPI, or generated SDK files.
- Proxy package tests only if changing shared proxy behavior, not for each new endpoint.
Binary Protobuf Question
If someone asks why the proxy uses protojson instead of protobuf bytes:
- A binary payload is possible because the cloud handler already has a typed proto request and the site side resolves the method descriptor.
- The merged design chose protojson for the Temporal payload so non-secret fields remain readable during debugging, while selected secret fields are encrypted separately.
- Switching to bytes would reduce encode/decode overhead and lean harder on protobuf wire compatibility, but it would make Temporal history opaque and require a different redaction strategy for secret fields.
- Treat binary transport as a follow-up design change to the shared proxy, not as part of adding a normal REST endpoint through the existing proxy.
Known Example
Use the BMC credential endpoint from PR 2477 as the reference pattern:
- Handler:
rest-api/api/pkg/api/handler/bmccredential.go. - Model:
rest-api/api/pkg/api/model/bmccredential.go. - Core method:
/forge.Forge/CreateCredential. - Secret redaction:
password. - Response omits password and returns only accepted metadata.
More from NVIDIA
View publishernemoclaw-user-guide
retrieve NemoClaw documentation and configuration
NemoClaw
Jul 20DocumentationMCPSearchmcore-build-and-dependency
manage Megatron-LM development environments
Megatron-LM
Jul 27ContainersDeploymentPythonmcore-bump-base-image
update NVIDIA PyTorch base images
Megatron-LM
Jul 14CI/CDDeploymentmcore-cicd
manage CI/CD pipelines for Megatron-LM
Megatron-LM
Jul 27CI/CDDeploymentGitHubmcore-create-issue
investigate CI failures and create issues
Megatron-LM
Jul 14DebuggingGitHubTriagemcore-linting-and-formatting
lint and format Megatron-LM code
Megatron-LM
Jul 14Best PracticesCode Analysis