AnnouncementsIntroducing Arkoren

    Menu

    Secrets Overview

    Load private application credentials through a secret store without confusing storage with runtime configuration.

    What's on this page
    1. Read current text, byte, or typed JSON values and distinguish missing secrets from provider failures.
    2. Share literal name definitions without treating namespaces as schemas or authorization boundaries.
    3. Validate required startup credentials and keep names, values, and owned copies out of ordinary diagnostics.
    On this page

    A service needs credentials such as a reporting API token without putting them in source code or its container image. A secret store holds those private values outside the application; secret.Store reads them through your chosen driver. Provider permissions, retention, and auditing remain part of that provider’s configuration.

    Reading a secret produces an ordinary Go value. The facade does not cache it, refresh a running client, or revoke the credential in the system that accepts it. Rotation coordinates those separate changes.

    Reading Values

    With a configured *secret.Store named secrets and an operation context ctx, read a provisioned text credential:

    token, err := secrets.String(ctx, "reporting-token")

    On success, token contains the current value. String converts bytes to a Go string without validating UTF-8. For binary material, use Raw instead; its returned byte slice belongs to you. Azure accepts only UTF-8 text and Vault stores JSON objects, so choose the payload format before provisioning.

    A missing name or requested version wraps secret.ErrNotFound. Permission, authentication, and connectivity failures are not missing-secret signals. Use errors.Is for portable error checks rather than matching provider text. An already-canceled context fails with its context error without changing storage.

    Focused examples keep error results visible but omit routine propagation. Handle errors before using results; the startup example below retains the check that prevents using a missing credential.

    Typed Credentials

    When one credential contains related fields, store a JSON object and share a definition that binds its provider name to a Go type. Import secret from arkoren.dev/core/service/secret:

    type ReportingCredentials struct {
    	Account string `json:"account"`
    	Token   string `json:"token"`
    }
    
    var reportingSecret = secret.NewSecret[ReportingCredentials]("reporting-client")

    The definition performs no I/O and creates no provider resource. After provisioning that JSON secret, read it through the facade:

    credentials, err := secrets.Get(ctx, reportingSecret)

    On success, credentials has type ReportingCredentials. Validate required fields before using them: a shared definition is not a provider schema, and independent definitions can assign different types to the same name.

    Definitions are immutable and safe to share. An empty name or zero definition reports secret.ErrInvalidSecret; Err() checks this without a read. Get rejects invalid definitions before provider I/O, with an already-canceled context taking precedence. JSON decoding errors can include the name and underlying details; neither decoded values nor returned errors are redacted.

    Shared Names

    For several JSON credentials of the same type, a namespace composes their names. Choose a separator valid for your provider rather than assuming slash paths work everywhere:

    reports := secret.NewNamespace[ReportingCredentials]("reports", "-")
    archiveSecret := reports.Secret("archive")
    credentials, err := secrets.Get(ctx, archiveSecret)

    This reads the literal name reports-archive; it does not create a namespace in the provider or grant access. Azure needs flat names. Google accepts a full resource path or an unqualified ID with a configured project; slashes in a full resource path are not valid separators inside that ID. AWS and Vault permit path-style conventions. See Drivers before choosing deployed names.

    Derive publishes an independent variant. Subnamespace joins a child prefix with the parent’s separator before applying settings for future joins:

    regional := reports.Subnamespace("eu")
    replicaSecret := regional.Secret("replica")

    The resulting name is reports-eu-replica. No escaping or normalization occurs, and an empty separator concatenates components. Validate or unambiguously encode untrusted components to prevent collisions. Namespaces are not authorization or isolation boundaries.

    Empty prefixes, empty child names, and zero namespaces are invalid; descendants retain the first declaration error. Name, Separator, and Err inspect a namespace. Construction callbacks run once in order, including on invalid declarations; nil callbacks panic, and retained drafts cannot change published values.

    Startup Loading

    If a client uses its credential only during construction, load and validate the credential before starting that client. A required-secret failure should stop startup rather than silently select an empty value or generate a replacement. For a safe application-owned error, import the standard-library errors package:

    token, err := secrets.String(ctx, "reporting-token")
    if err != nil {
    	return errors.New("reporting credential could not be loaded")
    }
    if token == "" {
    	return errors.New("reporting credential is empty")
    }

    Only the success path passes token to the reporting client. The generic error avoids exposing the provider error or secret name through ordinary startup logs; use a protected diagnostic path if you need the underlying cause. A successful read checks storage access, not whether the reporting API accepts that token.

    Use environment settings for nonsecret choices such as the deployment’s project or vault address. Grant each runtime identity access only to the secrets it needs. Keeping store reads out of request handling removes those reads from the request path, but a store outage can still prevent startup or refresh.

    Private Values

    Treat secret names as potentially private as well as their contents. Typed definitions and namespaces redact identities under ordinary formatting and structured logging, but Name() deliberately exposes them. Raw Reference and Value records, strings, decoded structs, native objects, and returned errors do not inherit that protection.

    Do not log credentials or credential-bearing connection strings, include them in public URLs, or return them in API responses. Limit which application objects retain them. Driver diagnostic records mask selected fields only; consult the provider logging rules, particularly when supplying native clients.

    Drivers copy input and returned bytes. Clearing your returned slice does not clear storage, other copies, strings, or decoded fields; copying a secret.Value record alone still shares its Data slice. Arkoren does not guarantee secret zeroization. Deleting a secret does not erase values already held by consumers.

    For all definitions and operations, see the secret API reference.

    Open a bulk documentation archive?

    This file contains every guide in its scope, not API declarations. Loading it all into an agent can exhaust its context window and increase processing time and cost. For coding tasks, start with the index and read only the relevant pages.

    Use the full archive for offline indexing, bulk processing, or deliberate large-context use.

    Browse the index instead
    Open archive