Documentation
¶
Overview ¶
Package musereelsdk is the public SDK boundary for controlled MuseReel workbench instances. It provides the authentication, assertion-signing, Gateway HTTP, and runtime control-plane clients used by an authorized workbench process.
"Public" here names the S31 boundary offered to third-party backends. It is not a statement about publication: this repository stays private until the owner makes a public-release decision.
This package is intended for a controlled workbench instance, not for code embedded in a browser, mobile application, or other customer-controlled frontend. The main entry points are NewTLSConfig or DialRuntime for mTLS, NewGRPCTokenSource and NewRuntimeClient for runtime operations, and NewGatewayClient for authenticated invocation operations.
Index ¶
- Constants
- func CanonicalGatewayPath(route GatewayRoute, ids ...string) (string, error)
- func CanonicalPath(path string) (string, error)
- func DialRuntime(ctx context.Context, target string, config MTLSConfig, ...) (*grpc.ClientConn, error)
- func ErrorCode(err error) string
- func IsRuntimeUnauthenticated(err error) bool
- func NewMTLSCredentials(config MTLSConfig) (credentials.TransportCredentials, error)
- func NewTLSConfig(config MTLSConfig) (*tls.Config, error)
- func RequestFingerprint(method, canonicalPath, actor, idempotencyKey string, body []byte) (string, error)
- func RetryableGatewayCode(code string) bool
- func SignAssertion(signer Signer, input AssertionInput) (JWS, AssertionClaims, error)
- func ValidateCanonicalPath(path string) error
- type AssertionCall
- type AssertionClaims
- type AssertionInput
- type AuthenticatedClient
- type CachedTokenSource
- type Clock
- type ECDSAP256Signer
- func (signer *ECDSAP256Signer) Algorithm() string
- func (signer *ECDSAP256Signer) Format(state fmt.State, verb rune)
- func (signer *ECDSAP256Signer) GoString() string
- func (signer *ECDSAP256Signer) KeyID() string
- func (signer *ECDSAP256Signer) MarshalJSON() ([]byte, error)
- func (signer *ECDSAP256Signer) Sign(message []byte) ([]byte, error)
- func (signer *ECDSAP256Signer) String() string
- type Ed25519Signer
- func (signer *Ed25519Signer) Algorithm() string
- func (signer *Ed25519Signer) Format(state fmt.State, verb rune)
- func (signer *Ed25519Signer) GoString() string
- func (signer *Ed25519Signer) KeyID() string
- func (signer *Ed25519Signer) MarshalJSON() ([]byte, error)
- func (signer *Ed25519Signer) Sign(message []byte) ([]byte, error)
- func (signer *Ed25519Signer) String() string
- type ErrorCodeProvider
- type GRPCTokenSource
- type GatewayActorFunc
- type GatewayCancelResponse
- type GatewayClient
- func (client *GatewayClient) Cancel(ctx context.Context, invocationID, idempotencyKey string) (GatewayCancelResponse, error)
- func (client *GatewayClient) CreateAsync(ctx context.Context, request GatewayCreateRequest, idempotencyKey string) (GatewayCreateResponse, error)
- func (client *GatewayClient) CreateStream(ctx context.Context, request GatewayCreateRequest, idempotencyKey string) (GatewayCreateResponse, error)
- func (client *GatewayClient) DownloadArtifact(ctx context.Context, invocationID, artifactID string, dst io.Writer) error
- func (client *GatewayClient) Get(ctx context.Context, invocationID string) (GatewayGetResponse, error)
- func (client *GatewayClient) GetWithETag(ctx context.Context, invocationID, etag string) (GatewayGetResponse, error)
- func (client *GatewayClient) NewPoller(invocationID string) (*GatewayPoller, error)
- type GatewayClientOption
- type GatewayCreateRequest
- type GatewayCreateResponse
- type GatewayDeliveryMode
- type GatewayError
- type GatewayGetResponse
- type GatewayIdentity
- type GatewayInvocationSnapshot
- type GatewayInvocationSpec
- type GatewayInvocationState
- type GatewayPoller
- type GatewayRoute
- type GatewaySSEDisconnectError
- type GatewaySSEEvent
- type GatewaySSEStream
- type JWS
- type MTLSConfig
- type RuntimeAssertionConfig
- type RuntimeClient
- func (client *RuntimeClient) ConfirmRegistration(ctx context.Context, request *runtimepb.ConfirmRegistrationRequest, ...) (*runtimepb.RegistrationReply, error)
- func (client *RuntimeClient) CreateOrder(ctx context.Context, request *runtimepb.CreateOrderRequest, ...) (*runtimepb.CreateOrderReply, error)
- func (client *RuntimeClient) DisableIdentity(ctx context.Context, request *runtimepb.DisableIdentityRequest, ...) (*runtimepb.IdentityReply, error)
- func (client *RuntimeClient) GetBalance(ctx context.Context, request *runtimepb.GetBalanceRequest, ...) (*runtimepb.BalanceReply, error)
- func (client *RuntimeClient) GetOfferCatalog(ctx context.Context, options ...grpc.CallOption) (*runtimepb.OfferCatalogReply, error)
- func (client *RuntimeClient) GetOrder(ctx context.Context, request *runtimepb.GetOrderRequest, ...) (*runtimepb.GetOrderReply, error)
- func (client *RuntimeClient) GetSkuCatalog(ctx context.Context, request *runtimepb.GetSkuCatalogRequest, ...) (*runtimepb.SkuCatalogReply, error)
- func (client *RuntimeClient) ListBalanceLots(ctx context.Context, request *runtimepb.ListBalanceLotsRequest, ...) (*runtimepb.BalanceLotsReply, error)
- func (client *RuntimeClient) ListLedger(ctx context.Context, request *runtimepb.ListLedgerRequest, ...) (*runtimepb.LedgerReply, error)
- func (client *RuntimeClient) ListSiteBranding(ctx context.Context, options ...grpc.CallOption) (*runtimepb.ListSiteBrandingReply, error)
- func (client *RuntimeClient) ResolveRegistration(ctx context.Context, request *runtimepb.ResolveRegistrationRequest, ...) (*runtimepb.RegistrationIntent, error)
- func (client *RuntimeClient) SyncIdentity(ctx context.Context, request *runtimepb.SyncIdentityRequest, ...) (*runtimepb.IdentityReply, error)
- func (client *RuntimeClient) SyncVerificationStatus(ctx context.Context, request *runtimepb.SyncVerificationStatusRequest, ...) (*runtimepb.IdentityReply, error)
- func (client *RuntimeClient) VerifyAndConfirmPayment(ctx context.Context, request *runtimepb.VerifyAndConfirmPaymentRequest, ...) (*runtimepb.VerifyAndConfirmPaymentReply, error)
- type RuntimeClientOption
- type RuntimeRPCError
- type SecretString
- type Signer
- type Token
- func (token Token) AccessToken() string
- func (token Token) ExpiresAt() time.Time
- func (token Token) Format(state fmt.State, verb rune)
- func (token Token) GoString() string
- func (token Token) MarshalJSON() ([]byte, error)
- func (token Token) RequestID() string
- func (token Token) String() string
- func (token Token) TokenType() string
- type TokenExchangeFunc
- type TokenInvalidator
- type TokenSource
- type TokenSourceOption
Examples ¶
Constants ¶
const ( RuntimeUnauthenticated = "runtime_unauthenticated" ActorAssertionInvalid = "actor_assertion_invalid" ActorAssertionReplayed = "actor_assertion_replayed" )
RuntimeUnauthenticated, ActorAssertionInvalid, and ActorAssertionReplayed are stable runtime error codes. SDK branches use these codes rather than unstable human-readable status text or transport status alone.
const ( GatewayInvalidInvocationRequest = "invalid_invocation_request" GatewayModerationInvalidRequest = "moderation_invalid_request" GatewayRuntimeUnauthenticated = RuntimeUnauthenticated GatewayActorAssertionInvalid = ActorAssertionInvalid GatewayActorAssertionReplayed = ActorAssertionReplayed GatewayRuntimeForbidden = "runtime_forbidden" GatewaySKUNotAllowed = "sku_not_allowed" GatewayComplianceRejected = "compliance_rejected" GatewayInvocationNotFound = "invocation_not_found" GatewayInvocationArtifactNotFound = "invocation_artifact_not_found" GatewayInvocationArtifactExpired = "invocation_artifact_expired" GatewayInvocationDeliveryModeMismatch = "invocation_delivery_mode_mismatch" GatewayInvocationIdempotencyConflict = "invocation_idempotency_conflict" GatewayInvocationTransitionConflict = "invocation_transition_conflict" GatewayInsufficientQuota = "insufficient_quota" GatewayMemberLimitExceeded = "member_limit_exceeded" GatewayRateLimited = "rate_limited" GatewayInternalError = "internal_error" )
Gateway error codes are the HTTP SDK's only stable values for branching; human-readable messages are for diagnostics only.
const ( // registration resolution being temporarily unavailable. RuntimeRegistrationUnavailable = "registration_unavailable" // RuntimeRegistrationCodeInvalid is the stable non-retryable error code for // an invite code that is not usable at this site. RuntimeRegistrationCodeInvalid = "registration_code_invalid" // RuntimeRegistrationCodeExpired is the stable non-retryable error code for // an invite code that was usable but can no longer be used. RuntimeRegistrationCodeExpired = "registration_code_expired" // RuntimeRegistrationCodeNotFound is the stable non-retryable error code for // an invite code that does not exist. // // Deprecated: As of hub S78 the server no longer exposes // registration_code_not_found at the transport boundary; use // RuntimeRegistrationCodeInvalid for an invite code that is unusable under // the current contract. RuntimeRegistrationCodeNotFound = "registration_code_not_found" // RuntimeRegistrationCodeMerchantMismatch is the stable non-retryable error // code for an invite code that does not match the site's merchant. // // Deprecated: As of hub S78 the server no longer exposes // registration_code_merchant_mismatch at the transport boundary; use // RuntimeRegistrationCodeInvalid for an invite code that is unusable under // the current contract. RuntimeRegistrationCodeMerchantMismatch = "registration_code_merchant_mismatch" // RuntimeQueryInvalid is the stable error code for an invalid balance or // ledger query request. RuntimeQueryInvalid = "runtime_query_invalid" // that is temporarily unavailable. RuntimeSubjectUnavailable = "runtime_subject_unavailable" // RuntimeIdentityInactive is the stable error code for an inactive identity. RuntimeIdentityInactive = "identity_inactive" )
const MinimumTLSVersion uint16 = tls.VersionTLS12
MinimumTLSVersion is the explicit lower bound for SDK mTLS connections.
Variables ¶
This section is empty.
Functions ¶
func CanonicalGatewayPath ¶
func CanonicalGatewayPath(route GatewayRoute, ids ...string) (string, error)
CanonicalGatewayPath builds and validates a registered invocation path. The route-specific IDs are server-issued path segments and therefore must already be URL-safe; the SDK never URL-escapes them as part of fingerprint construction. Create accepts no IDs, get/cancel accept one invocation ID, and get_artifact accepts an invocation ID followed by an artifact ID.
Example ¶
package main
import (
"fmt"
musereelsdk "github.com/emiya-dev/musereel-sdk"
)
func main() {
path, err := musereelsdk.CanonicalGatewayPath(
musereelsdk.GatewayInvocationGetArtifact,
"invocation-example",
"artifact-example",
)
if err != nil {
panic(err)
}
fmt.Println(path)
}
Output: /runtime/v1/invocations/invocation-example/artifacts/artifact-example
func CanonicalPath ¶
CanonicalPath validates an already assembled canonical path and returns it unchanged. Canonicalization here is validation, not normalization: any spelling that would require normalization is rejected to keep fingerprints stable across clients.
func DialRuntime ¶
func DialRuntime(ctx context.Context, target string, config MTLSConfig, options ...grpc.DialOption) (*grpc.ClientConn, error)
DialRuntime opens an mTLS grpc connection. ExchangeRuntimeToken selects its temporary internal wire codec per call, so this connection remains usable by future generated protobuf clients as well.
func IsRuntimeUnauthenticated ¶
IsRuntimeUnauthenticated reports only the stable runtime code. A generic codes.Unauthenticated status is deliberately insufficient to trigger a credential refresh.
func NewMTLSCredentials ¶
func NewMTLSCredentials(config MTLSConfig) (credentials.TransportCredentials, error)
NewMTLSCredentials returns grpc transport credentials using NewTLSConfig.
func NewTLSConfig ¶
func NewTLSConfig(config MTLSConfig) (*tls.Config, error)
NewTLSConfig loads the CA and validates the current client key pair. The returned config deliberately leaves Certificates empty: GetClientCertificate re-reads the pair for every handshake, allowing atomic file replacement to rotate the certificate without a watcher or background goroutine.
func RequestFingerprint ¶
func RequestFingerprint(method, canonicalPath, actor, idempotencyKey string, body []byte) (string, error)
RequestFingerprint computes the frozen SHA-256 fingerprint. Empty body is canonicalized as {}, and the returned base64url has no padding.
Example ¶
package main
import (
"fmt"
musereelsdk "github.com/emiya-dev/musereel-sdk"
)
func main() {
fingerprint, err := musereelsdk.RequestFingerprint(
"POST",
"/runtime/v1/invocations",
"actor@example",
"idempotency-example",
[]byte(`{"prompt":"hello"}`),
)
if err != nil {
panic(err)
}
fmt.Println(fingerprint)
}
Output: 3YxxQLRqVlYoGoNNxmyczn1pDG7af8dsKcxKqqF9kqU
func RetryableGatewayCode ¶
RetryableGatewayCode returns the frozen code table's default retryability decision.
It cannot see this response's wire retryable value, so it always returns true for internal_error. When a *GatewayError is available, use RetryableByCode instead; see GatewayError for the distinction.
func SignAssertion ¶
func SignAssertion(signer Signer, input AssertionInput) (JWS, AssertionClaims, error)
SignAssertion creates a compact JWS with a fresh random nonce on every invocation. Its maximum validity window is the frozen 60 seconds.
Example ¶
package main
import (
"crypto/ed25519"
"crypto/rand"
"time"
musereelsdk "github.com/emiya-dev/musereel-sdk"
)
func main() {
_, privateKey, err := ed25519.GenerateKey(rand.Reader)
if err != nil {
panic(err)
}
signer, err := musereelsdk.NewEd25519Signer("example-assertion-kid", privateKey)
if err != nil {
panic(err)
}
assertion, claims, err := musereelsdk.SignAssertion(signer, musereelsdk.AssertionInput{
InstanceID: "instance-example",
TenantID: "tenant-example",
SessionID: "session-example",
Actor: "actor@example",
Operation: string(musereelsdk.GatewayInvocationCreate),
Method: "POST",
CanonicalPath: "/runtime/v1/invocations",
Body: []byte(`{"sku_id":"text.generate.v1"}`),
IdempotencyKey: "idempotency-example",
IssuedAt: time.Unix(1700000000, 0),
TTL: time.Minute,
})
if err != nil {
panic(err)
}
_ = assertion.Compact()
_ = claims.RequestFingerprint
}
Output:
func ValidateCanonicalPath ¶
ValidateCanonicalPath accepts exactly registered gateway invocation paths and runtime.v1.RuntimeService full method paths.
Types ¶
type AssertionCall ¶
type AssertionCall struct {
Args any
IdempotencyKey string
RequestFingerprint string
Sign func(Token) (JWS, error)
ApplyAssertion func(args any, assertion JWS) error
ReadIdentity func(args any) (idempotencyKey, requestFingerprint string, err error)
}
AssertionCall describes the small amount of request-specific behavior needed when a retry must receive a fresh nonce. ApplyAssertion changes only the actor_assertion field in Args. ReadIdentity is an optional negative control: when supplied, the client proves that idempotency key and request fingerprint did not change across the refresh retry.
type AssertionClaims ¶
type AssertionClaims struct {
Issuer string `json:"iss"`
Subject string `json:"sub"`
Audience string `json:"aud"`
TenantID string `json:"tenant_id"`
SessionID string `json:"session_id"`
Operation string `json:"operation"`
RequestFingerprint string `json:"request_fingerprint"`
IssuedAt int64 `json:"iat"`
ExpiresAt int64 `json:"exp"`
Nonce string `json:"nonce"`
}
AssertionClaims is the fixed actor assertion payload.
func VerifyCompactJWS ¶
func VerifyCompactJWS(compact string, publicKey crypto.PublicKey) (AssertionClaims, error)
VerifyCompactJWS verifies an SDK compact JWS and returns its fixed claims. It is intended for tests and local self-checks; server registration remains the source of truth for kid authorization.
type AssertionInput ¶
type AssertionInput struct {
InstanceID string
TenantID string
SessionID string
Actor string
Operation string
Method string
CanonicalPath string
Body []byte
IdempotencyKey string
IssuedAt time.Time
TTL time.Duration
}
AssertionInput contains token-bound identity context and the current operation request. InstanceID and TenantID are assertion claims supplied by the caller's already-bound runtime-token context; they are never put into the empty ExchangeRuntimeTokenRequest.
type AuthenticatedClient ¶
type AuthenticatedClient struct {
// contains filtered or unexported fields
}
AuthenticatedClient adds a Bearer token to generic unary grpc calls and retries exactly once after the stable runtime_unauthenticated code. It does not inspect or rewrite business request fields.
func NewAuthenticatedClient ¶
func NewAuthenticatedClient(connection grpc.ClientConnInterface, tokens TokenSource) *AuthenticatedClient
NewAuthenticatedClient constructs a generic authenticated unary caller.
Example ¶
package main
import (
"context"
"time"
musereelsdk "github.com/emiya-dev/musereel-sdk"
)
func main() {
now := time.Unix(1700000000, 0)
tokens := musereelsdk.NewCachedTokenSource(
func(context.Context) (musereelsdk.Token, error) {
return musereelsdk.NewToken("example-token", "Bearer", now.Add(5*time.Minute))
},
musereelsdk.WithClock(func() time.Time { return now }),
)
client := musereelsdk.NewAuthenticatedClient(nil, tokens)
_ = client
}
Output:
func (*AuthenticatedClient) Invoke ¶
func (client *AuthenticatedClient) Invoke(ctx context.Context, method string, args, reply any, options ...grpc.CallOption) error
Invoke calls method with a Bearer token. The same args and reply values are passed to the one allowed retry, preserving caller-owned idempotency keys and request fingerprints.
func (*AuthenticatedClient) InvokeWithAssertion ¶
func (client *AuthenticatedClient) InvokeWithAssertion(ctx context.Context, method string, call AssertionCall, reply any, options ...grpc.CallOption) error
InvokeWithAssertion is the assertion-aware form of Invoke. It signs once per attempt, so a token-refresh retry gets a new nonce while the supplied business identity remains fixed.
type CachedTokenSource ¶
type CachedTokenSource struct {
// contains filtered or unexported fields
}
CachedTokenSource provides lazy refresh, a fixed 60-second refresh window, and single-flight exchange behavior for any exchange function.
func NewCachedTokenSource ¶
func NewCachedTokenSource(exchange TokenExchangeFunc, options ...TokenSourceOption) *CachedTokenSource
NewCachedTokenSource constructs a cache around an exchange function.
Example ¶
package main
import (
"context"
"time"
musereelsdk "github.com/emiya-dev/musereel-sdk"
)
func main() {
now := time.Unix(1700000000, 0)
source := musereelsdk.NewCachedTokenSource(
func(context.Context) (musereelsdk.Token, error) {
return musereelsdk.NewToken("example-token", "Bearer", now.Add(5*time.Minute))
},
musereelsdk.WithClock(func() time.Time { return now }),
)
token, err := source.Token(context.Background())
if err != nil {
panic(err)
}
_ = token.AccessToken()
}
Output:
func (*CachedTokenSource) Invalidate ¶
func (source *CachedTokenSource) Invalidate()
Invalidate discards the cached token. An exchange already in flight is not cancelled; its result is still the single-flight result for waiting callers.
type Clock ¶
Clock is injectable for deterministic token lifetime tests and callers with a controlled time source.
type ECDSAP256Signer ¶
type ECDSAP256Signer struct {
// contains filtered or unexported fields
}
ECDSAP256Signer implements ES256 with the JWS-required fixed-width R||S signature encoding rather than ASN.1 DER.
func NewES256Signer ¶
func NewES256Signer(kid string, key *ecdsa.PrivateKey) (*ECDSAP256Signer, error)
NewES256Signer validates and copies the P-256 private key.
Example ¶
package main
import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
musereelsdk "github.com/emiya-dev/musereel-sdk"
)
func main() {
privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
panic(err)
}
signer, err := musereelsdk.NewES256Signer("example-es256-kid", privateKey)
if err != nil {
panic(err)
}
_ = signer
}
Output:
func NewES256SignerFromPEM ¶
func NewES256SignerFromPEM(kid string, pemBytes []byte) (*ECDSAP256Signer, error)
NewES256SignerFromPEM parses a PKCS#8 or SEC1 PEM private key.
Example ¶
package main
import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/x509"
"encoding/pem"
musereelsdk "github.com/emiya-dev/musereel-sdk"
)
func main() {
privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
panic(err)
}
der, err := x509.MarshalPKCS8PrivateKey(privateKey)
if err != nil {
panic(err)
}
pemBytes := pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: der})
signer, err := musereelsdk.NewES256SignerFromPEM("example-es256-kid", pemBytes)
if err != nil {
panic(err)
}
_ = signer
}
Output:
func (*ECDSAP256Signer) Algorithm ¶
func (signer *ECDSAP256Signer) Algorithm() string
Algorithm returns the registered JWS algorithm name, "ES256".
func (*ECDSAP256Signer) Format ¶
func (signer *ECDSAP256Signer) Format(state fmt.State, verb rune)
Format writes the fixed "[REDACTED_PRIVATE_KEY]" placeholder for every formatting verb, so formatting cannot expose the signer's private key.
func (*ECDSAP256Signer) GoString ¶
func (signer *ECDSAP256Signer) GoString() string
GoString returns the fixed "[REDACTED_PRIVATE_KEY]" placeholder for %#v formatting. It intentionally never formats the signer's private key.
func (*ECDSAP256Signer) KeyID ¶
func (signer *ECDSAP256Signer) KeyID() string
KeyID returns the key identifier supplied when the signer was constructed. It returns an empty string for a nil receiver.
func (*ECDSAP256Signer) MarshalJSON ¶
func (signer *ECDSAP256Signer) MarshalJSON() ([]byte, error)
MarshalJSON encodes the fixed "[REDACTED_PRIVATE_KEY]" placeholder instead of the signer's private key.
func (*ECDSAP256Signer) Sign ¶
func (signer *ECDSAP256Signer) Sign(message []byte) ([]byte, error)
Sign returns an ES256 signature for message using SHA-256 and the JWS fixed-width R||S encoding. It returns an error when the signer is nil or does not contain a configured P-256 private key.
func (*ECDSAP256Signer) String ¶
func (signer *ECDSAP256Signer) String() string
String returns the fixed "[REDACTED_PRIVATE_KEY]" placeholder. It intentionally never formats the signer's private key.
type Ed25519Signer ¶
type Ed25519Signer struct {
// contains filtered or unexported fields
}
Ed25519Signer implements the registered EdDSA algorithm.
func NewEd25519Signer ¶
func NewEd25519Signer(kid string, key ed25519.PrivateKey) (*Ed25519Signer, error)
NewEd25519Signer validates and copies an Ed25519 private key.
Example ¶
package main
import (
"crypto/ed25519"
"crypto/rand"
musereelsdk "github.com/emiya-dev/musereel-sdk"
)
func main() {
_, privateKey, err := ed25519.GenerateKey(rand.Reader)
if err != nil {
panic(err)
}
signer, err := musereelsdk.NewEd25519Signer("example-ed25519-kid", privateKey)
if err != nil {
panic(err)
}
_ = signer
}
Output:
func NewEd25519SignerFromPEM ¶
func NewEd25519SignerFromPEM(kid string, pemBytes []byte) (*Ed25519Signer, error)
NewEd25519SignerFromPEM parses a PKCS#8 PEM private key.
Example ¶
package main
import (
"crypto/ed25519"
"crypto/rand"
"crypto/x509"
"encoding/pem"
musereelsdk "github.com/emiya-dev/musereel-sdk"
)
func main() {
_, privateKey, err := ed25519.GenerateKey(rand.Reader)
if err != nil {
panic(err)
}
der, err := x509.MarshalPKCS8PrivateKey(privateKey)
if err != nil {
panic(err)
}
pemBytes := pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: der})
signer, err := musereelsdk.NewEd25519SignerFromPEM("example-ed25519-kid", pemBytes)
if err != nil {
panic(err)
}
_ = signer
}
Output:
func (*Ed25519Signer) Algorithm ¶
func (signer *Ed25519Signer) Algorithm() string
Algorithm returns the registered JWS algorithm name, "EdDSA".
func (*Ed25519Signer) Format ¶
func (signer *Ed25519Signer) Format(state fmt.State, verb rune)
Format writes the fixed "[REDACTED_PRIVATE_KEY]" placeholder for every formatting verb, so formatting cannot expose the signer's private key.
func (*Ed25519Signer) GoString ¶
func (signer *Ed25519Signer) GoString() string
GoString returns the fixed "[REDACTED_PRIVATE_KEY]" placeholder for %#v formatting. It intentionally never formats the signer's private key.
func (*Ed25519Signer) KeyID ¶
func (signer *Ed25519Signer) KeyID() string
KeyID returns the key identifier supplied when the signer was constructed. It returns an empty string for a nil receiver.
func (*Ed25519Signer) MarshalJSON ¶
func (signer *Ed25519Signer) MarshalJSON() ([]byte, error)
MarshalJSON encodes the fixed "[REDACTED_PRIVATE_KEY]" placeholder instead of the signer's private key.
func (*Ed25519Signer) Sign ¶
func (signer *Ed25519Signer) Sign(message []byte) ([]byte, error)
Sign returns an Ed25519 signature for message. It returns an error when the signer is nil or does not contain a correctly sized private key.
func (*Ed25519Signer) String ¶
func (signer *Ed25519Signer) String() string
String returns the fixed "[REDACTED_PRIVATE_KEY]" placeholder. It intentionally never formats the signer's private key.
type ErrorCodeProvider ¶
type ErrorCodeProvider interface {
ErrorCode() string
}
ErrorCodeProvider is an optional application error shape for stable Sluice codes. grpc status errors are also recognized when their status message is exactly a frozen code or starts with that code followed by a delimiter.
type GRPCTokenSource ¶
type GRPCTokenSource struct {
// contains filtered or unexported fields
}
GRPCTokenSource exchanges the empty runtime token request through the generated protobuf client message, then applies CachedTokenSource lifetime and single-flight semantics.
func NewGRPCTokenSource ¶
func NewGRPCTokenSource(connection grpc.ClientConnInterface, options ...TokenSourceOption) *GRPCTokenSource
NewGRPCTokenSource constructs a token source backed by RuntimeService.
func (*GRPCTokenSource) Invalidate ¶
func (source *GRPCTokenSource) Invalidate()
Invalidate discards the gRPC source's cached token.
type GatewayActorFunc ¶
GatewayActorFunc supplies the actor at request time. It is resolved once per logical request, and a token-refresh retry reuses the same value.
type GatewayCancelResponse ¶
type GatewayCancelResponse struct {
StatusCode int
RequestID string
InvocationID string
Accepted bool
Snapshot *GatewayInvocationSnapshot
}
GatewayCancelResponse represents either a newly accepted cancellation intent (202) or the current snapshot (200).
type GatewayClient ¶
type GatewayClient struct {
// contains filtered or unexported fields
}
GatewayClient wraps the four authenticated Gateway invocation routes.
func NewGatewayClient ¶
func NewGatewayClient(baseURL string, tlsConfig *tls.Config, tokens TokenSource, signer Signer, identity GatewayIdentity, options ...GatewayClientOption) (*GatewayClient, error)
NewGatewayClient constructs an authenticated Gateway HTTP client. Callers provide TLS configuration from NewTLSConfig and the token and signer abstractions shared by the rest of the SDK.
Example ¶
package main
import (
"context"
"crypto/ed25519"
"crypto/rand"
"crypto/tls"
"time"
musereelsdk "github.com/emiya-dev/musereel-sdk"
)
func main() {
_, privateKey, err := ed25519.GenerateKey(rand.Reader)
if err != nil {
panic(err)
}
signer, err := musereelsdk.NewEd25519Signer("example-gateway-kid", privateKey)
if err != nil {
panic(err)
}
now := time.Unix(1700000000, 0)
tokens := musereelsdk.NewCachedTokenSource(
func(context.Context) (musereelsdk.Token, error) {
return musereelsdk.NewToken("example-token", "Bearer", now.Add(5*time.Minute))
},
musereelsdk.WithClock(func() time.Time { return now }),
)
client, err := musereelsdk.NewGatewayClient(
"https://gateway.example.invalid",
&tls.Config{MinVersion: musereelsdk.MinimumTLSVersion},
tokens,
signer,
musereelsdk.GatewayIdentity{
InstanceID: "instance-example",
TenantID: "tenant-example",
SessionID: "session-example",
Actor: "actor@example",
},
)
if err != nil {
panic(err)
}
_ = client
}
Output:
func (*GatewayClient) Cancel ¶
func (client *GatewayClient) Cancel(ctx context.Context, invocationID, idempotencyKey string) (GatewayCancelResponse, error)
Cancel sends a bodyless DELETE using the idempotency key held by the caller.
func (*GatewayClient) CreateAsync ¶
func (client *GatewayClient) CreateAsync(ctx context.Context, request GatewayCreateRequest, idempotencyKey string) (GatewayCreateResponse, error)
CreateAsync sends an async-mode create request and returns its snapshot.
func (*GatewayClient) CreateStream ¶
func (client *GatewayClient) CreateStream(ctx context.Context, request GatewayCreateRequest, idempotencyKey string) (GatewayCreateResponse, error)
CreateStream sends a stream-mode create request and returns its SSE stream.
func (*GatewayClient) DownloadArtifact ¶
func (client *GatewayClient) DownloadArtifact(ctx context.Context, invocationID, artifactID string, dst io.Writer) error
DownloadArtifact verifies Content-Digest before writing any bytes to dst.
func (*GatewayClient) Get ¶
func (client *GatewayClient) Get(ctx context.Context, invocationID string) (GatewayGetResponse, error)
Get retrieves the current snapshot without an idempotency key.
This method is intentionally not dead code. An SDK-013 reconciliation review once misclassified it as unused: Sluice's integration rehearsal module (test/rehearsal, a separate Go module that replaces this repository through a sibling directory) has real call sites in golden/golden_test.go and golden/completed_test.go, and Sluice's ci.sh full harness compiles and runs that module. Removing Get would not fail this repository's own gates, but it would make another repository's gate fail to compile. It therefore remains public because it has a consumer.
func (*GatewayClient) GetWithETag ¶
func (client *GatewayClient) GetWithETag(ctx context.Context, invocationID, etag string) (GatewayGetResponse, error)
GetWithETag sends If-None-Match when etag is non-empty. A 304 response is returned with NotModified=true rather than as an error.
func (*GatewayClient) NewPoller ¶
func (client *GatewayClient) NewPoller(invocationID string) (*GatewayPoller, error)
NewPoller creates an ETag-aware poller for an invocation.
type GatewayClientOption ¶
type GatewayClientOption func(*gatewayClientConfig)
GatewayClientOption customizes SDK-local behavior only.
func WithGatewayClock ¶
func WithGatewayClock(now Clock) GatewayClientOption
WithGatewayClock injects the clock used for assertion issuance and polling metadata tests. It does not change the maximum 60-second wire TTL.
type GatewayCreateRequest ¶
type GatewayCreateRequest struct {
SKU string `json:"sku_id"`
TaskRef string `json:"task_ref"`
Spec GatewayInvocationSpec `json:"spec"`
ModerationReceipt string `json:"moderation_receipt"`
// QualityTier distinguishes the legacy absent field (nil) from an explicit
// platform-default empty tier. The SDK never accepts supplier or model
// selectors here.
QualityTier *string `json:"quality_tier,omitempty"`
}
GatewayCreateRequest contains the four required create-body fields plus the optional public quality_tier selector. It does not contain delivery_mode; the delivery mode is a SKU catalog attribute.
Example ¶
package main
import (
musereelsdk "github.com/emiya-dev/musereel-sdk"
)
func main() {
qualityTier := "q2"
request := musereelsdk.GatewayCreateRequest{
SKU: "image.generate.v1",
TaskRef: "task-example",
Spec: musereelsdk.GatewayInvocationSpec{
SchemaVersion: "1",
Input: map[string]string{"prompt": "hello"},
Parameters: map[string]string{"image_count": "1", "resolution": "512", "quality": qualityTier},
},
ModerationReceipt: "opaque-receipt",
QualityTier: &qualityTier,
}
if err := request.Validate(); err != nil {
panic(err)
}
}
Output:
func (GatewayCreateRequest) Validate ¶
func (request GatewayCreateRequest) Validate() error
Validate checks the request shape before the SDK creates a token or assertion for the request.
type GatewayCreateResponse ¶
type GatewayCreateResponse struct {
StatusCode int
RequestID string
InvocationID string
Location string
AlreadyExists bool
Snapshot *GatewayInvocationSnapshot
Stream *GatewaySSEStream
}
GatewayCreateResponse is shared by both create modes. A 303 response is represented by AlreadyExists=true and a non-empty InvocationID with a nil error; for stream mode, the caller owns and must close Stream.
type GatewayDeliveryMode ¶
type GatewayDeliveryMode string
GatewayDeliveryMode is determined by the Gateway-side SKU catalog. The SDK exposes separate methods for the delivery modes; delivery_mode is not put in the request body and is never silently overridden by the SDK.
const ( GatewayDeliveryStream GatewayDeliveryMode = "stream" GatewayDeliveryAsync GatewayDeliveryMode = "async" )
type GatewayError ¶
type GatewayError struct {
Code string `json:"code"`
Message string `json:"message"`
// Retryable is a direct read of the wire value for diagnostics; do not use it
// to decide whether to retry. When the server omits retryable, this field is
// false, while the contract's conservative default for an unregistered
// internal code is true (06:611-619). This one field therefore gives the
// opposite answer to the effective decision. Always use RetryableByCode or
// IsRetryable: only they can see whether the wire carried the field at all.
Retryable bool `json:"retryable"`
RetryAfterMS *int64 `json:"retry_after_ms"`
Details map[string]any `json:"details"`
HTTPStatus int `json:"-"`
RequestID string `json:"-"`
InvocationID string `json:"-"`
// contains filtered or unexported fields
}
GatewayError is the stable shape of a Gateway HTTP error. Retryable preserves the wire value for diagnostics; SDK-created errors use the frozen code table as their default.
Call RetryableByCode or IsRetryable for retry decisions; do not call RetryableGatewayCode directly when you have a GatewayError. The two once happened to be equivalent, but they are not now: RetryableGatewayCode takes only a code string and cannot see this response's retryable value, so it always returns true for internal_error. The contract (06:611-619) says the retryable value of internal_error is not a constant: a deterministic deployment-configuration failure arrives as internal_error with retryable=false, and the caller must stop retrying. Only RetryableByCode and IsRetryable can see the wire value. RetryableGatewayCode remains for the conservative default when the caller has only a code string.
func (GatewayError) Error ¶
func (err GatewayError) Error() string
Error intentionally omits Message so that server diagnostic text cannot accidentally carry a full token or assertion into an error string.
func (GatewayError) ErrorCode ¶
func (err GatewayError) ErrorCode() string
ErrorCode implements the SDK's ErrorCodeProvider error shape.
func (GatewayError) IsRetryable ¶
func (err GatewayError) IsRetryable() bool
IsRetryable is the explicit method form of RetryableByCode.
func (GatewayError) RetryableByCode ¶
func (err GatewayError) RetryableByCode() bool
RetryableByCode returns the effective retryability decision for an invocation error without changing the GatewayError.Retryable field. For an internal_error received over HTTP, an explicit server value is used instead of the code-table default.
func (*GatewayError) UnmarshalJSON ¶
func (err *GatewayError) UnmarshalJSON(data []byte) error
UnmarshalJSON preserves numeric values in Details without loss by using json.Number and extracts InvocationID from the frozen details field.
type GatewayGetResponse ¶
type GatewayGetResponse struct {
StatusCode int
RequestID string
Snapshot *GatewayInvocationSnapshot
NotModified bool
ETag string
RetryAfter time.Duration
}
GatewayGetResponse contains either a new snapshot or a 304 result. ETag and RetryAfter are metadata used by GatewayPoller.
type GatewayIdentity ¶
type GatewayIdentity struct {
InstanceID string
TenantID string
SessionID string
Actor string
ActorFunc GatewayActorFunc
}
GatewayIdentity is the token-bound identity context required by SignAssertion for Gateway requests.
type GatewayInvocationSnapshot ¶
type GatewayInvocationSnapshot struct {
ID string `json:"id"`
// Version is int64 because the server's respond.go and the 06 contract
// example ("version": 1) both encode it as a JSON number. Declaring it a string
// made every real Gateway snapshot fail to decode (async create 202, GET 200,
// and cancel all became protocol errors); the SDK fixtures once sent a quoted
// value and therefore incorrectly reinforced that assumption.
Version int64 `json:"version"`
State GatewayInvocationState `json:"state"`
Terminal bool `json:"terminal"`
SKU string `json:"sku_id"`
TaskRef string `json:"task_ref"`
CreatedAtMS int64 `json:"created_at_ms"`
UpdatedAtMS int64 `json:"updated_at_ms"`
ReservedUnits *string `json:"reserved_units"`
SettledUnits *string `json:"settled_units"`
Result json.RawMessage `json:"result"`
Error *GatewayError `json:"error"`
LotDeductions json.RawMessage `json:"lot_deductions"`
}
GatewayInvocationSnapshot is shared by async create, GET, and cancel responses. Result and LotDeductions remain raw JSON; the SDK does not convert units or similar amount-like values to floating-point numbers.
type GatewayInvocationSpec ¶
type GatewayInvocationSpec struct {
SchemaVersion string `json:"schema_version"`
Input any `json:"input"`
Parameters any `json:"parameters"`
}
GatewayInvocationSpec is the frozen spec object. Input and Parameters use interface values, so callers may provide json.RawMessage or ordinary Go JSON values. Validate rejects JSON numbers that cannot be canonicalized (fractions, exponent notation, or values outside int64); integer forms are accepted.
type GatewayInvocationState ¶
type GatewayInvocationState string
GatewayInvocationState is the closed set of states used by invocation snapshots.
const ( GatewayStateAccepted GatewayInvocationState = "accepted" GatewayStateRunning GatewayInvocationState = "running" GatewayStateCancelPending GatewayInvocationState = "cancel_pending" GatewayStateReconciling GatewayInvocationState = "reconciling" GatewayStateSettlementShortfall GatewayInvocationState = "settlement_shortfall" GatewayStateCompleted GatewayInvocationState = "completed" GatewayStateFailed GatewayInvocationState = "failed" GatewayStateCancelled GatewayInvocationState = "cancelled" )
type GatewayPoller ¶
type GatewayPoller struct {
// contains filtered or unexported fields
}
GatewayPoller maintains the ETag and waits for the server's Retry-After before the next GET. An SSE disconnect does not cause it to POST or DELETE.
func (*GatewayPoller) ETag ¶
func (poller *GatewayPoller) ETag() string
ETag returns the poller's current validator.
func (*GatewayPoller) Poll ¶
func (poller *GatewayPoller) Poll(ctx context.Context) (GatewayGetResponse, error)
Poll performs one GET and updates the ETag. It first blocks until the previous response's Retry-After has elapsed, so a caller in a loop does not need to sleep itself.
type GatewayRoute ¶
type GatewayRoute string
GatewayRoute identifies one of the four invocation routes frozen for the assertion fingerprint surface.
const ( GatewayInvocationCreate GatewayRoute = "invocation:create" GatewayInvocationGet GatewayRoute = "invocation:get" GatewayInvocationGetArtifact GatewayRoute = "invocation:get_artifact" GatewayInvocationCancel GatewayRoute = "invocation:cancel" )
type GatewaySSEDisconnectError ¶
type GatewaySSEDisconnectError struct{}
GatewaySSEDisconnectError indicates that the HTTP stream ended before a terminal event. Callers should resume the invocation with GatewayPoller or Get.
func (GatewaySSEDisconnectError) Error ¶
func (GatewaySSEDisconnectError) Error() string
Error returns the stable message used for a pre-terminal SSE disconnect.
func (GatewaySSEDisconnectError) Unwrap ¶
func (GatewaySSEDisconnectError) Unwrap() error
Unwrap reports io.ErrUnexpectedEOF so callers can classify the disconnect with errors.Is.
type GatewaySSEEvent ¶
type GatewaySSEEvent struct {
ID string
Event string
RequestID string
InvocationID string
Sequence int64
OccurredAtMS int64
Payload json.RawMessage
}
GatewaySSEEvent is a validated business event. Payload remains raw JSON; the SDK does not retype streaming results or units.
type GatewaySSEStream ¶
type GatewaySSEStream struct {
// contains filtered or unexported fields
}
GatewaySSEStream parses a text/event-stream response. A disconnect before a terminal event returns GatewaySSEDisconnectError and is never converted into a cancellation request.
func (*GatewaySSEStream) Close ¶
func (stream *GatewaySSEStream) Close() error
Close releases the underlying HTTP response body.
func (*GatewaySSEStream) Next ¶
func (stream *GatewaySSEStream) Next() (GatewaySSEEvent, error)
Next returns the next business event. It skips comments such as : keep-alive and unknown SSE fields; a normal EOF after a terminal event is io.EOF.
func (*GatewaySSEStream) Pending ¶
func (stream *GatewaySSEStream) Pending() bool
Pending reports whether the terminal event was invocation.pending. In that case, callers should switch to GET polling.
func (*GatewaySSEStream) Terminal ¶
func (stream *GatewaySSEStream) Terminal() bool
Terminal reports whether a terminal or pending event has been observed.
type JWS ¶
type JWS struct {
// contains filtered or unexported fields
}
JWS is a compact actor assertion. Its compact value is redacted by default and can only be obtained through Compact for transmission.
func SignActorAssertion ¶
func SignActorAssertion(signer Signer, input AssertionInput) (JWS, error)
SignActorAssertion is a convenience form when callers only need the transport value.
Example ¶
package main
import (
"crypto/ed25519"
"crypto/rand"
musereelsdk "github.com/emiya-dev/musereel-sdk"
)
func main() {
_, privateKey, err := ed25519.GenerateKey(rand.Reader)
if err != nil {
panic(err)
}
signer, err := musereelsdk.NewEd25519Signer("example-actor-kid", privateKey)
if err != nil {
panic(err)
}
assertion, err := musereelsdk.SignActorAssertion(signer, musereelsdk.AssertionInput{
InstanceID: "instance-example",
TenantID: "tenant-example",
SessionID: "session-example",
Actor: "actor@example",
Operation: string(musereelsdk.GatewayInvocationCreate),
Method: "POST",
CanonicalPath: "/runtime/v1/invocations",
Body: []byte(`{"sku_id":"text.generate.v1"}`),
IdempotencyKey: "idempotency-example",
})
if err != nil {
panic(err)
}
_ = assertion.Bytes()
}
Output:
func (JWS) Format ¶
Format writes the fixed "[REDACTED]" placeholder for every formatting verb, so formatting cannot expose the compact JWS.
func (JWS) GoString ¶
GoString returns the fixed "[REDACTED]" placeholder for %#v formatting instead of the compact JWS.
func (JWS) MarshalJSON ¶
MarshalJSON encodes the fixed "[REDACTED]" placeholder instead of the compact JWS, so ordinary JSON serialization cannot expose the assertion.
type MTLSConfig ¶
MTLSConfig identifies the local client certificate, private key, and CA bundle. The private key is read only inside the TLS stack and is never included in errors or formatted configuration output.
Example ¶
package main
import (
musereelsdk "github.com/emiya-dev/musereel-sdk"
)
func main() {
config := musereelsdk.MTLSConfig{
CertFile: "/path/to/client.crt",
KeyFile: "/path/to/client.key",
CAFile: "/path/to/ca.pem",
ServerName: "gateway.example.invalid",
}
_ = config
}
Output:
type RuntimeAssertionConfig ¶
type RuntimeAssertionConfig struct {
Signer Signer
InstanceID string
TenantID string
SessionID string
}
RuntimeAssertionConfig holds the signing context for runtime actor assertions. Each RPC generates operation, path, body, and idempotency-key values according to the frozen contract; callers cannot override them.
type RuntimeClient ¶
type RuntimeClient struct {
// contains filtered or unexported fields
}
RuntimeClient is the typed control-plane wrapper for runtime.v1.RuntimeService. ExchangeRuntimeToken is not part of this client; GRPCTokenSource performs it through the mTLS bootstrap. Like the other RPCs without assertions, ResolveRegistration uses AuthenticatedClient to send a Bearer token and retains the single refresh retry for the stable unauthenticated code.
func NewRuntimeClient ¶
func NewRuntimeClient(connection grpc.ClientConnInterface, tokens TokenSource, options ...RuntimeClientOption) *RuntimeClient
NewRuntimeClient constructs a runtime control-plane client. tokens is used by every RPC that requires a Bearer token, including ResolveRegistration.
Example ¶
package main
import (
"context"
"crypto/ed25519"
"crypto/rand"
"time"
musereelsdk "github.com/emiya-dev/musereel-sdk"
runtimepb "github.com/emiya-dev/musereel-sdk/runtime"
)
func main() {
_, privateKey, err := ed25519.GenerateKey(rand.Reader)
if err != nil {
panic(err)
}
signer, err := musereelsdk.NewEd25519Signer("example-runtime-kid", privateKey)
if err != nil {
panic(err)
}
now := time.Unix(1700000000, 0)
tokens := musereelsdk.NewCachedTokenSource(
func(context.Context) (musereelsdk.Token, error) {
return musereelsdk.NewToken("example-token", "Bearer", now.Add(5*time.Minute))
},
musereelsdk.WithClock(func() time.Time { return now }),
)
client := musereelsdk.NewRuntimeClient(
nil,
tokens,
musereelsdk.WithRuntimeAssertion(signer, "instance-example", "tenant-example", "session-example"),
)
catalogRequest := &runtimepb.GetSkuCatalogRequest{Actor: "actor@example"}
_ = client
_ = catalogRequest
}
Output:
func (*RuntimeClient) ConfirmRegistration ¶
func (client *RuntimeClient) ConfirmRegistration(ctx context.Context, request *runtimepb.ConfirmRegistrationRequest, intent *runtimepb.RegistrationIntent, options ...grpc.CallOption) (*runtimepb.RegistrationReply, error)
ConfirmRegistration builds the fixed JCS assertion body from the intent's fingerprint. The intent token remains only in the protobuf request and does not enter the assertion fingerprint. The actor itself is the idempotency-key exception for this RPC and is allowed to contain up to 256 bytes of UTF-8 under the contract.
func (*RuntimeClient) CreateOrder ¶
func (client *RuntimeClient) CreateOrder(ctx context.Context, request *runtimepb.CreateOrderRequest, options ...grpc.CallOption) (*runtimepb.CreateOrderReply, error)
CreateOrder binds offer_price_id and, when present, the requested variable Offer amount into the signed request fingerprint. It protects one order creation with idempotency_key. It does not modify the price identifier or amount; binding means the assertion covers exactly the Offer price and caller-supplied amount this call was made against. Amounts are carried as strings without SDK parsing or reformatting, including an explicitly empty optional value so the server can reject it under its own contract.
func (*RuntimeClient) DisableIdentity ¶
func (client *RuntimeClient) DisableIdentity(ctx context.Context, request *runtimepb.DisableIdentityRequest, options ...grpc.CallOption) (*runtimepb.IdentityReply, error)
DisableIdentity sends an instance-scoped disabled event.
func (*RuntimeClient) GetBalance ¶
func (client *RuntimeClient) GetBalance(ctx context.Context, request *runtimepb.GetBalanceRequest, options ...grpc.CallOption) (*runtimepb.BalanceReply, error)
GetBalance uses an empty JSON body and a strict-nonce balance:get assertion.
func (*RuntimeClient) GetOfferCatalog ¶
func (client *RuntimeClient) GetOfferCatalog(ctx context.Context, options ...grpc.CallOption) (*runtimepb.OfferCatalogReply, error)
GetOfferCatalog sends an empty protobuf message with a Bearer token and does not generate an assertion.
func (*RuntimeClient) GetOrder ¶
func (client *RuntimeClient) GetOrder(ctx context.Context, request *runtimepb.GetOrderRequest, options ...grpc.CallOption) (*runtimepb.GetOrderReply, error)
GetOrder creates a query assertion with the fixed body {"order_id":"..."}.
func (*RuntimeClient) GetSkuCatalog ¶
func (client *RuntimeClient) GetSkuCatalog(ctx context.Context, request *runtimepb.GetSkuCatalogRequest, options ...grpc.CallOption) (*runtimepb.SkuCatalogReply, error)
GetSkuCatalog returns the actor-scoped public SKU catalog. It signs the frozen empty JCS body with operation catalog:get and an empty idempotency key. Every invocation, including a transparent token-refresh attempt, gets a fresh nonce because catalog queries use strict replay semantics.
func (*RuntimeClient) ListBalanceLots ¶
func (client *RuntimeClient) ListBalanceLots(ctx context.Context, request *runtimepb.ListBalanceLotsRequest, options ...grpc.CallOption) (*runtimepb.BalanceLotsReply, error)
ListBalanceLots passes through the opaque page_cursor. page_size=0 preserves the server default of 50; an explicit value must be 1-100. The strict-nonce body uses the request's original page_size.
func (*RuntimeClient) ListLedger ¶
func (client *RuntimeClient) ListLedger(ctx context.Context, request *runtimepb.ListLedgerRequest, options ...grpc.CallOption) (*runtimepb.LedgerReply, error)
ListLedger passes through the opaque page_cursor. page_size=0 preserves the server default of 50; an explicit value must be 1-100. The strict-nonce body uses the request's original page_size.
func (*RuntimeClient) ListSiteBranding ¶
func (client *RuntimeClient) ListSiteBranding(ctx context.Context, options ...grpc.CallOption) (*runtimepb.ListSiteBrandingReply, error)
ListSiteBranding sends an empty protobuf message with a Bearer token and does not generate an assertion.
It is an instance-level query that returns brand references for all sites in the instance. The contract carries no actor assertion, so it has the same shape as the offer catalog method: it is registered in runtimeMethods and runtimeQueryMethods, but not in runtimeAssertionOperations.
func (*RuntimeClient) ResolveRegistration ¶
func (client *RuntimeClient) ResolveRegistration(ctx context.Context, request *runtimepb.ResolveRegistrationRequest, options ...grpc.CallOption) (*runtimepb.RegistrationIntent, error)
ResolveRegistration resolves a registration intent in the authenticated mTLS and Bearer instance scope. request.Domain is a string supplied by the frontend; the SDK puts it in the protobuf request unchanged and does not derive, normalize, or complete it from Host, Origin, or configuration. request.InviteCode is only a channel identifier. An invite code that is not usable at the site is exposed at the transport boundary only as RuntimeRegistrationCodeInvalid; one that was usable but can no longer be used is exposed only as RuntimeRegistrationCodeExpired. Internal not_found and merchant_mismatch causes are not further distinguished at the SDK transport boundary because both are caller input errors and are not retryable.
An external caller should retry a server response with registration_unavailable at most once within a total two-second budget; the SDK does not implement that retry itself.
func (*RuntimeClient) SyncIdentity ¶
func (client *RuntimeClient) SyncIdentity(ctx context.Context, request *runtimepb.SyncIdentityRequest, options ...grpc.CallOption) (*runtimepb.IdentityReply, error)
SyncIdentity sends an instance-scoped identity lifecycle event. The three identity RPCs share one event_id namespace; the SDK validates the format but does not deduplicate across RPCs.
func (*RuntimeClient) SyncVerificationStatus ¶
func (client *RuntimeClient) SyncVerificationStatus(ctx context.Context, request *runtimepb.SyncVerificationStatusRequest, options ...grpc.CallOption) (*runtimepb.IdentityReply, error)
SyncVerificationStatus accepts only the proto-frozen verified, verified_at_ms, credential_ref, and issuer payload. It has no PII input. The client validates the ASCII format of credential_ref and issuer.
func (*RuntimeClient) VerifyAndConfirmPayment ¶
func (client *RuntimeClient) VerifyAndConfirmPayment(ctx context.Context, request *runtimepb.VerifyAndConfirmPaymentRequest, options ...grpc.CallOption) (*runtimepb.VerifyAndConfirmPaymentReply, error)
VerifyAndConfirmPayment passes the payment proof through unchanged. The SDK does not parse signed_payload, signed_headers, or provider_query_ref, and it does not provide a "mark as paid" semantic.
type RuntimeClientOption ¶
type RuntimeClientOption func(*RuntimeClient)
RuntimeClientOption configures local RuntimeClient behavior.
func WithRuntimeAssertion ¶
func WithRuntimeAssertion(signer Signer, instanceID, tenantID, sessionID string) RuntimeClientOption
WithRuntimeAssertion is a convenience form of WithRuntimeAssertionConfig.
func WithRuntimeAssertionConfig ¶
func WithRuntimeAssertionConfig(config RuntimeAssertionConfig) RuntimeClientOption
WithRuntimeAssertionConfig supplies the signer and token-bound identity context shared by the RPCs that require actor assertions.
type RuntimeRPCError ¶
type RuntimeRPCError struct {
// contains filtered or unexported fields
}
RuntimeRPCError preserves the underlying gRPC error while exposing the server's stable code and retryable semantics. It keeps an existing server status code and applies the contract's status mapping for frozen stable codes when necessary.
func (*RuntimeRPCError) Error ¶
func (err *RuntimeRPCError) Error() string
Error returns the underlying gRPC error message, or an empty string for a nil receiver or a wrapper without an underlying error.
func (*RuntimeRPCError) ErrorCode ¶
func (err *RuntimeRPCError) ErrorCode() string
ErrorCode implements ErrorCodeProvider without changing the frozen ErrorCode implementation in errors.go.
func (*RuntimeRPCError) GRPCStatus ¶
func (err *RuntimeRPCError) GRPCStatus() *status.Status
GRPCStatus keeps status.Code and status.Convert useful after the stable-code wrapper is applied.
func (*RuntimeRPCError) Retryable ¶
func (err *RuntimeRPCError) Retryable() bool
Retryable reports the frozen retryability of the returned runtime error. RuntimeClient itself does not retry registration_unavailable.
func (*RuntimeRPCError) Unwrap ¶
func (err *RuntimeRPCError) Unwrap() error
Unwrap returns the underlying gRPC error so errors.Is and errors.As can inspect the original cause. It returns nil for a nil receiver.
type SecretString ¶
type SecretString struct {
// contains filtered or unexported fields
}
SecretString holds a value that must be explicitly revealed before it is used as a protocol string. Its default formatting and JSON encoding never include the value.
func (SecretString) Format ¶
func (s SecretString) Format(state fmt.State, verb rune)
Format writes the fixed "[REDACTED]" placeholder for every formatting verb, so formatting cannot expose the stored value.
func (SecretString) GoString ¶
func (s SecretString) GoString() string
GoString returns the fixed "[REDACTED]" placeholder for %#v formatting instead of the stored value.
func (SecretString) MarshalJSON ¶
func (s SecretString) MarshalJSON() ([]byte, error)
MarshalJSON encodes the fixed "[REDACTED]" placeholder instead of the stored value.
func (SecretString) Reveal ¶
func (s SecretString) Reveal() string
Reveal returns the secret for an explicit protocol operation. Callers should avoid storing or formatting the returned string.
func (SecretString) String ¶
func (s SecretString) String() string
String returns the fixed "[REDACTED]" placeholder instead of the stored value.
type Signer ¶
Signer signs a JWS signing input using one of the two algorithms registered for SDK-002. Implementations keep private key material private and redact it from all default formatting.
type Token ¶
type Token struct {
// contains filtered or unexported fields
}
Token is an opaque short-lived runtime access token. The raw token can only be obtained through the explicitly named AccessToken method; default formatting and JSON encoding are redacted.
func NewToken ¶
NewToken constructs a token for custom TokenSource implementations. It does not accept or encode tenant, instance, or scope data.
Example ¶
package main
import (
"time"
musereelsdk "github.com/emiya-dev/musereel-sdk"
)
func main() {
token, err := musereelsdk.NewToken(
"example-token",
"Bearer",
time.Unix(1700000000, 0).Add(5*time.Minute),
)
if err != nil {
panic(err)
}
_ = token.TokenType()
}
Output:
func (Token) AccessToken ¶
AccessToken reveals the opaque token for an Authorization header.
func (Token) Format ¶
Format writes the fixed "[REDACTED]" placeholder for every formatting verb, so formatting cannot expose the access token.
func (Token) GoString ¶
GoString returns the fixed "[REDACTED]" placeholder for %#v formatting instead of the access token.
func (Token) MarshalJSON ¶
MarshalJSON encodes token metadata while replacing AccessToken with the fixed "[REDACTED]" placeholder. RequestID is omitted when empty, and the token type and expiry are retained.
func (Token) RequestID ¶
RequestID returns the exchange request identifier, when the server sent one.
type TokenExchangeFunc ¶
TokenExchangeFunc exchanges the bootstrap mTLS identity for a token.
type TokenInvalidator ¶
type TokenInvalidator interface {
Invalidate()
}
TokenInvalidator is implemented by SDK token sources whose cache can be discarded after a stable runtime_unauthenticated response.
type TokenSource ¶
TokenSource supplies a currently usable runtime token.
type TokenSourceOption ¶
type TokenSourceOption func(*tokenSourceConfig)
TokenSourceOption customizes local token-source behavior without changing the wire request. In particular, there is no tenant, instance, or scope field here because ExchangeRuntimeToken is intentionally an empty message.
func WithClock ¶
func WithClock(now Clock) TokenSourceOption
WithClock injects the clock used for cache expiry decisions.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package jcs implements the RFC 8785 subset frozen by the Sluice server, whose live implementation is backend/pkg/app/core/jcs.go in the sluice repository.
|
Package jcs implements the RFC 8785 subset frozen by the Sluice server, whose live implementation is backend/pkg/app/core/jcs.go in the sluice repository. |