Python & TypeScript · read-only secrets
Python & TypeScript · segredos somente leitura
One contract.
Any secret store.
Um contrato.
Qualquer cofre de segredos.
Your code asks for database/password. Whether that lives in AWS Secrets Manager, GCP Parameter Manager or a dictionary in a test does not change the call — only which distribution you install.
Seu código pede database/password. Se isso mora no AWS Secrets Manager, no GCP Parameter Manager ou num dicionário de teste, a chamada não muda — muda apenas qual distribuição você instala.
from secret_kernel.factory import ( CreateSecretClientConfig, create_secret_client, ) from secret_kernel.provider_aws_parameter_store import ( AwsParameterStoreProviderOptions, ) client = create_secret_client( CreateSecretClientConfig( provider="aws-parameter-store", env="prod", project="billing", options=AwsParameterStoreProviderOptions( region="us-east-1", ), ) ) secret = await client.get_secret("database/password") # secret.value — reads /prod/billing/database/password
import { SecretProvider, createSecretClient, } from '@secret-kernel/factory'; const client = await createSecretClient({ provider: SecretProvider.AwsParameterStore, env: 'prod', project: 'billing', options: { region: 'us-east-1' }, }); const secret = await client.getSecret('database/password'); // secret.value — reads /prod/billing/database/password
What it refuses to do
O que ele se recusa a fazer
The scope is the feature. A narrow contract is one you can reason about.
O escopo é a feature. Um contrato estreito é um contrato sobre o qual você consegue raciocinar.
- Read-only. No write, no delete, no rotation, no batch read, no explicit historical version.
- Latest version only. When a provider supports versions, the kernel always reads the current one.
- Cross-environment reads are opt-in, one call at a time. The client's
envapplies unless a call says otherwise. Replacing it is never implicit and never a default, andomit_envomitEnvstill wins over it — a service reading another environment is usually a defect, but the caller sometimes knows better than the process context. - Provider options never leak.
regionbelongs to AWS,project_idprojectIdto GCP. The shared contract knows neither. - Failures are never cached. A missing secret that appears later is found on the next read.
- Somente leitura. Sem escrita, remoção, rotação, leitura em lote ou versão histórica explícita.
- Apenas a última versão. Quando o provider suporta versões, o kernel sempre lê a atual.
- Leitura entre ambientes é opt-in, uma chamada por vez. O
envdo client vale a menos que uma chamada diga o contrário. Substituí-lo nunca é implícito nem default, eomit_envomitEnvcontinua vencendo — um serviço lendo outro ambiente é normalmente um defeito, mas quem chama às vezes sabe mais que o contexto do processo. - Opções de provider não vazam.
regioné da AWS,project_idprojectIdé do GCP. O contrato compartilhado não conhece nenhuma das duas. - Falhas nunca são cacheadas. Um segredo ausente que aparece depois é encontrado na leitura seguinte.
Writing, rotating and versioning stay outside this contract by design.
Escrita, rotação e versionamento ficam fora deste contrato por decisão de projeto.
Install and first read
Instalação e primeira leitura
Nothing is bundled. Install the contract, the shared core, the factory and the one provider you need.
Nada vem embutido. Instale o contrato, o core compartilhado, a factory e o único provider de que você precisa.
Step 1 · install the base
Passo 1 · instale a base
The contract, the shared core and the factory. No provider yet — that is step 2, and it is a separate distribution so an AWS-only service never pulls a GCP SDK.
O contrato, o core compartilhado e a factory. Nenhum provider ainda — isso é o passo 2, e ele é uma distribuição separada, então um serviço só-AWS nunca baixa um SDK do GCP.
contracts depends on nothing. A consumer that only declares types or catches errors installs that one package alone.
contracts não depende de nada. Quem só declara tipos ou captura erros instala apenas esse pacote.
$ uv add secret-kernel-contracts secret-kernel-core \
secret-kernel-factory
$ npm install @secret-kernel/contracts @secret-kernel/core \
@secret-kernel/factory
Step 2 · add a provider and read
Passo 2 · adicione um provider e leia
Pick where the secret lives. The call is identical either way — only the provider alias and its typed options change, which is the whole point of the contract.
Escolha onde o segredo mora. A chamada é idêntica nos dois casos — mudam apenas o alias do provider e suas opções tipadas, que é justamente o propósito do contrato.
in-memory
For local development, CI and tests. Reads preloaded values or environment variables, so nothing needs a cloud account.
Para desenvolvimento local, CI e testes. Lê valores pré-carregados ou variáveis de ambiente, então nada precisa de conta em nuvem.
With env_secretsenvSecrets, the key is the resolved name without the leading slash, non-alphanumerics replaced by _, uppercased and prefixed: /dev/my-app/database becomes SECRET_KERNEL_DEV_MY_APP_DATABASE. Preloaded secrets win over the environment.
Com env_secretsenvSecrets, a chave é o nome resolvido sem a barra inicial, não-alfanuméricos trocados por _, em maiúsculas e com prefixo: /dev/my-app/database vira SECRET_KERNEL_DEV_MY_APP_DATABASE. Segredos pré-carregados vencem o ambiente.
$ uv add secret-kernel-provider-in-memory
$ npm install @secret-kernel/provider-in-memory
from secret_kernel.factory import ( CreateSecretClientConfig, create_secret_client, ) from secret_kernel.provider_in_memory import ( InMemoryProviderOptions, ) client = create_secret_client( CreateSecretClientConfig( provider="in-memory", env="dev", project="my-app", options=InMemoryProviderOptions( secrets={"/dev/my-app/database/password": "s3cr3t"}, env_secrets=True, ), ) ) secret = await client.get_secret("database/password") # secret.value == "s3cr3t"
import { SecretProvider, createSecretClient, } from '@secret-kernel/factory'; const client = await createSecretClient({ provider: SecretProvider.InMemory, env: 'dev', project: 'my-app', options: { secrets: { '/dev/my-app/database/password': 's3cr3t' }, envSecrets: true, }, }); const secret = await client.getSecret('database/password'); // secret.value === 's3cr3t'
aws-parameter-store
For a real store. Reads SecureString parameters, the low-cost option in AWS.
Para um cofre de verdade. Lê parâmetros SecureString, a opção de baixo custo na AWS.
Pass credentials to be explicit, or leave it out and the AWS SDK's own chain applies. Explicit credentials take precedence.
Passe credentials para ser explícito, ou omita e a própria cadeia do SDK da AWS se aplica. Credenciais explícitas têm precedência.
Only the provider and its options differ from the block above. get_secretgetSecret is the same call.
Só o provider e suas opções diferem do bloco acima. get_secretgetSecret é a mesma chamada.
$ uv add secret-kernel-provider-aws-parameter-store
$ npm install @secret-kernel/provider-aws-parameter-store
from secret_kernel.provider_aws_parameter_store import ( AwsParameterStoreProviderOptions, ) client = create_secret_client( CreateSecretClientConfig( provider="aws-parameter-store", env="prod", project="billing", options=AwsParameterStoreProviderOptions( region="us-east-1", ), ) ) secret = await client.get_secret("database/password") # reads /prod/billing/database/password
const client = await createSecretClient({ provider: SecretProvider.AwsParameterStore, env: 'prod', project: 'billing', options: { region: 'us-east-1' }, }); const secret = await client.getSecret('database/password'); // reads /prod/billing/database/password
How a name is built
Como um nome é montado
A secret name is joined from what the client knows and what the call asks for.
O nome do segredo é montado a partir do que o client sabe e do que a chamada pede.
/prod /billing /— /database/password /prod/billing/database/password
All three leading parts are optional: a client with none of them reads /database/password.
As três primeiras partes são opcionais: um client sem nenhuma delas lê /database/password.
| Part | Parte | Accepts a slash | Aceita barra | Rule | Regra |
|---|---|---|---|---|---|
env |
No | Não | The deployment context — prod, staging. A single segment. A slash here would silently add a level, and the caller would only find out through a secret that cannot be found. |
O contexto de deploy — prod, staging. Um único segmento. Uma barra aqui adicionaria um nível silenciosamente, e quem chamou só descobriria por um segredo que não é encontrado. |
|
project |
No | Não | Groups a set of secrets, usually one service or application. Same rule as env. |
Agrupa um conjunto de segredos, normalmente um serviço ou aplicação. Mesma regra do env. |
|
prefix |
Yes | Sim | Adds any further levels you want. A string or a list of segments. A per-call prefix replaces the client's rather than adding to it. | Adiciona quantos níveis você quiser. Uma string ou uma lista de segmentos. Um prefix por chamada substitui o do client em vez de somar a ele. | |
name | name |
Yes | Sim | What the call asks for. Accepts /, because adding levels is exactly what it is for. |
O que a chamada pede. Aceita /, porque adicionar níveis é exatamente para isso que serve. |
Changing the name for one call
Mudando o nome para uma chamada
Each of the three client-level parts can be dropped, and each can be replaced.
Cada uma das três partes do nível do client pode ser derrubada, e cada uma pode ser substituída.
Omitting always wins over replacing. Passing both omit_projectomitProject and project drops the segment.
Omitir sempre vence substituir. Passar omit_projectomitProject e project juntos derruba o segmento.
Replacing env is never implicit: the client's value applies unless a call says otherwise, in that call alone. It exists for the caller who knows better than the process context — a local run reading the one secret that lives elsewhere.
Substituir o env nunca é implícito: o valor do client vale a menos que uma chamada diga o contrário, e só naquela chamada. Existe para quem chama e sabe mais que o contexto do processo — uma execução local lendo o único segredo que mora em outro lugar.
from secret_kernel.contracts import GetSecretOptions # /prod/billing/database — the client prefix is left out await client.get_secret( "database", GetSecretOptions(omit_prefix=True) ) # /prod/shared/api-key — read another project's secret await client.get_secret( "api-key", GetSecretOptions(project="shared") ) # /staging/billing/database/password — another environment, once await client.get_secret( "database/password", GetSecretOptions(env="staging") ) # /license-key — belongs to no environment or project await client.get_secret( "license-key", GetSecretOptions(omit_env=True, omit_project=True), )
// /prod/billing/database — the client prefix is left out await client.getSecret('database', { omitPrefix: true }); // /prod/shared/api-key — read another project's secret await client.getSecret('api-key', { project: 'shared' }); // /staging/billing/database/password — another environment, once await client.getSecret('database/password', { env: 'staging' }); // /license-key — belongs to no environment or project await client.getSecret('license-key', { omitEnv: true, omitProject: true, });
Reading structured secrets
Lendo segredos estruturados
A secret is a string by default. Ask for a parse mode and the value follows.
Um segredo é uma string por padrão. Peça um modo de parse e o valor acompanha.
Parse modes
Modos de parse
Two modes: JSON and KEY_VALUE. Keys and values are trimmed by default.
Dois modos: JSON e KEY_VALUE. Chaves e valores têm espaços removidos por padrão.
A secret that exists but cannot be parsed raises SecretParseError; parse results are never cached.
Um segredo que existe mas não pode ser parseado levanta SecretParseError; resultados de parse nunca são cacheados.
from secret_kernel.contracts import ( GetSecretOptions, SecretParseMode, ) # "s3cr3t" plain = await client.get_secret("database/password") # {"host": "db.internal", "port": 5432} config = await client.get_secret( "database/config", GetSecretOptions(parse=SecretParseMode.JSON) ) # {"user": "app", "password": "s3cr3t"} # from "user=app;password=s3cr3t" pairs = await client.get_secret( "database/credentials", GetSecretOptions(parse=SecretParseMode.KEY_VALUE), )
import { SecretParseMode } from '@secret-kernel/contracts'; // "s3cr3t" const plain = await client.getSecret('database/password'); // { host: 'db.internal', port: 5432 } type DbConfig = { host: string; port: number }; const config = await client.getSecret<DbConfig>( 'database/config', { parse: SecretParseMode.Json }, ); // { user: 'app', password: 's3cr3t' } // from "user=app;password=s3cr3t" const pairs = await client.getSecret( 'database/credentials', { parse: SecretParseMode.KeyValue }, );
Key-value conventions
Convenções chave-valor
If a project always stores key-value secrets the same way, set the convention once on the client instead of repeating it at every call.
Se um projeto sempre guarda segredos chave-valor do mesmo jeito, defina a convenção uma vez no client em vez de repeti-la em cada chamada.
A per-call parse_optionsparseOptions is merged over the client's field by field, so a call that needs one different separator does not have to restate the others.
Um parse_optionsparseOptions por chamada é mesclado sobre o do client campo por campo, então uma chamada que precisa de um separador diferente não precisa repetir os outros.
| Field | Campo | Default | Padrão |
|---|---|---|---|
pair_separatorpairSeparator | ";" | ||
key_value_separatorkeyValueSeparator | "=" | ||
keys | empty — names positional values that carry no separator | vazio — nomeia valores posicionais que não trazem separador | |
trim | Truetrue |
Empty pairs are ignored, empty values are kept as "", an empty key raises, and a repeated key keeps the last value.
Pares vazios são ignorados, valores vazios são mantidos como "", uma chave vazia levanta erro, e uma chave repetida mantém o último valor.
from secret_kernel.contracts import KeyValueParseOptions client = create_secret_client( CreateSecretClientConfig( provider="aws-parameter-store", env="prod", parse_options=KeyValueParseOptions( pair_separator="|", key_value_separator=":", ), options=AwsParameterStoreProviderOptions( region="us-east-1", ), ) ) # only the pair separator differs here; ":" is inherited await client.get_secret( "legacy", GetSecretOptions( parse=SecretParseMode.KEY_VALUE, parse_options=KeyValueParseOptions(pair_separator=";"), ), )
const client = await createSecretClient({ provider: SecretProvider.AwsParameterStore, env: 'prod', parseOptions: { pairSeparator: '|', keyValueSeparator: ':' }, options: { region: 'us-east-1' }, }); // only the pair separator differs here; ':' is inherited await client.getSecret('legacy', { parse: SecretParseMode.KeyValue, parseOptions: { pairSeparator: ';' }, });
Five providers, one call
Cinco providers, uma chamada
Provider options are typed per provider and never leak into the shared contract.
As opções de provider são tipadas por provider e nunca vazam para o contrato compartilhado.
| Provider | Distribution | Distribuição | Use for | Usar para |
|---|---|---|---|---|
in-memory |
secret-kernel-provider-in-memory@secret-kernel/provider-in-memory |
Local development, CI and tests. Reads preloaded values or environment variables. | Desenvolvimento local, CI e testes. Lê valores pré-carregados ou variáveis de ambiente. | |
aws-parameter-store |
secret-kernel-provider-aws-parameter-store@secret-kernel/provider-aws-parameter-store |
Low-cost secrets in AWS, as SecureString parameters. |
Segredos de baixo custo na AWS, como parâmetros SecureString. |
|
aws-secrets-manager |
secret-kernel-provider-aws-secrets-manager@secret-kernel/provider-aws-secrets-manager |
AWS secrets that need rotation and a dedicated lifecycle. Reads the AWSCURRENT stage; a binary-only secret raises SecretCapabilityNotSupportedError. |
Segredos da AWS que precisam de rotação e ciclo de vida próprio. Lê o estágio AWSCURRENT; um segredo apenas binário levanta SecretCapabilityNotSupportedError. |
|
gcp-parameter-manager |
secret-kernel-provider-gcp-parameter-manager@secret-kernel/provider-gcp-parameter-manager |
Low-cost secrets in GCP. Takes a location, defaulting to global. |
Segredos de baixo custo no GCP. Recebe um location, com padrão global. |
|
gcp-secret-manager |
secret-kernel-provider-gcp-secret-manager@secret-kernel/provider-gcp-secret-manager |
GCP secrets that need rotation and a dedicated lifecycle. | Segredos do GCP que precisam de rotação e ciclo de vida próprio. |
Credentials
Credenciais
Credentials are explicit when you pass them, and fall back to the cloud SDK's own chain when you do not. Explicit credentials take precedence.
As credenciais são explícitas quando você as passa, e caem para a própria cadeia do SDK da nuvem quando você não passa. Credenciais explícitas têm precedência.
Injecting a client keeps the SDK client under your lifecycle — the kernel closes only what it created.
Injetar um client mantém o client do SDK sob o seu ciclo de vida — o kernel fecha apenas o que ele mesmo criou.
Providers that cannot store / flatten the resolved name with a separator: AWS accepts /, _ and - and defaults to /; GCP accepts _ and - and defaults to _.
Providers que não conseguem guardar / achatam o nome resolvido com um separador: a AWS aceita /, _ e - e usa / como padrão; o GCP aceita _ e - e usa _.
from secret_kernel.provider_gcp_secret_manager import ( GcpSecretManagerProviderOptions, ) client = create_secret_client( CreateSecretClientConfig( provider="gcp-secret-manager", env="prod", project="billing", options=GcpSecretManagerProviderOptions( project_id="my-gcp-project", physical_name_separator="_", ), ) ) # reads projects/my-gcp-project/secrets/ # prod_billing_database_password/versions/latest
const client = await createSecretClient({ provider: SecretProvider.GcpSecretManager, env: 'prod', project: 'billing', options: { projectId: 'my-gcp-project', physicalNameSeparator: '_', }, }); // reads projects/my-gcp-project/secrets/ // prod_billing_database_password/versions/latest
Caching
Cache
Reads hit the provider every time unless you enable the cache.
As leituras vão ao provider todas as vezes, a menos que você habilite o cache.
The cache stores the decrypted string keyed by the resolved name, before any parsing, so the same secret read as JSON and as text costs one provider call.
O cache guarda a string descriptografada chaveada pelo nome resolvido, antes de qualquer parse, então o mesmo segredo lido como JSON e como texto custa uma chamada ao provider.
A value served from cache reports no version and no metadata: the cache stores the string only.
Um valor servido do cache não reporta version nem metadata: o cache guarda apenas a string.
Failures are never cached. A missing secret that appears later is found on the next read.
Falhas nunca são cacheadas. Um segredo ausente que aparece depois é encontrado na leitura seguinte.
Encryption in memory
Criptografia em memória
For a process that holds secrets in memory for a long time, cached values can be encrypted with AES-256-GCM. Without an encryption_keyencryptionKey the client generates one and keeps it in memory only.
Para um processo que mantém segredos em memória por muito tempo, os valores cacheados podem ser criptografados com AES-256-GCM. Sem uma encryption_keyencryptionKey, o client gera uma e a mantém apenas em memória.
What it protects against: a heap snapshot, or an accidental object dump. What it does not: code running inside the same process.
Contra o que protege: um snapshot de heap, ou um dump acidental de objeto. Contra o que não protege: código rodando dentro do mesmo processo.
from secret_kernel.contracts import SecretCacheOptions client = create_secret_client( CreateSecretClientConfig( provider="aws-secrets-manager", env="prod", cache=SecretCacheOptions( enabled=True, ttl_ms=300_000, max_entries=100, encrypt_in_memory=True, ), options=AwsSecretsManagerProviderOptions( region="us-east-1", ), ) )
const client = await createSecretClient({ provider: SecretProvider.AwsSecretsManager, env: 'prod', cache: { enabled: true, ttlMs: 300_000, maxEntries: 100, encryptInMemory: true, }, options: { region: 'us-east-1' }, });
Errors are part of the contract
Erros fazem parte do contrato
Every error carries provider, secret_namesecretName, code, ref and cause.
Todo erro carrega provider, secret_namesecretName, code, ref e cause.
Only not-found and permission are normalized. Every other failure keeps the message the SDK produced and gains provider, ref and code, with the original exception in cause.
Só não-encontrado e permissão são normalizados. Toda outra falha preserva a mensagem que o SDK produziu e ganha provider, ref e code, com a exceção original em cause.
This is why a missing secret raises SecretNotFoundError whichever provider is behind the contract — and why a provider-specific failure still tells you which SDK produced it.
É por isso que um segredo ausente levanta SecretNotFoundError qualquer que seja o provider por trás do contrato — e por isso que uma falha específica de provider ainda diz qual SDK a produziu.
from secret_kernel.contracts import ( SecretNotFoundError, SecretParseError, ) try: secret = await client.get_secret( "database/config", GetSecretOptions(parse=SecretParseMode.JSON), ) except SecretNotFoundError as error: logger.warning("missing %s on %s", error.ref, error.provider) raise except SecretParseError as error: logger.error( "unparseable %s", error.ref, exc_info=error.__cause__ ) raise
import { SecretNotFoundError, SecretParseError, } from '@secret-kernel/contracts'; try { const secret = await client.getSecret('database/config', { parse: SecretParseMode.Json, }); } catch (error) { if (error instanceof SecretNotFoundError) { logger.warn(`missing ${error.ref} on ${error.provider}`); } else if (error instanceof SecretParseError) { logger.error(`unparseable ${error.ref}`, { cause: error.cause, }); } throw error; }
| Class | Classe | Raised when | Levantado quando |
|---|---|---|---|
SecretNotFoundError | The secret or parameter does not exist. | O segredo ou parâmetro não existe. | |
SecretPermissionError | The provider refused the read. | O provider recusou a leitura. | |
SecretParseError | The secret was read but the requested parse failed. | O segredo foi lido, mas o parse pedido falhou. | |
InvalidSecretNameError | The resolved name is empty or unusable. | O nome resolvido está vazio ou inutilizável. | |
SecretCapabilityNotSupportedError | The provider cannot serve the request under the base contract. | O provider não consegue atender ao pedido dentro do contrato base. | |
SecretConfigurationError | Required, invalid or mutually exclusive configuration. | Configuração obrigatória, inválida ou mutuamente exclusiva. | |
SecretProviderError | Any other provider failure. | Qualquer outra falha do provider. |
Observability, and your own provider
Observabilidade, e seu próprio provider
Silent unless you ask, and open to a store the kernel has never heard of.
Silencioso a menos que você peça, e aberto a um cofre que o kernel nunca viu.
Lifecycle events
Eventos de ciclo de vida
Pass a logger to receive lifecycle events, or debug to send them to the console. Without either, the client is silent.
Passe um logger para receber eventos de ciclo de vida, ou debug para mandá-los ao console. Sem nenhum dos dois, o client fica silencioso.
Bring your own provider
Traga seu próprio provider
The factory accepts a provider class directly, so a store this package has never heard of is used through the same contract. The factory asserts the class declares the requested provider_nameproviderName.
A factory aceita uma classe de provider diretamente, então um cofre que este pacote nunca viu é usado pelo mesmo contrato. A factory verifica que a classe declara o provider_nameproviderName pedido.
The shared contract suite in the testing package runs every portable guarantee against it — decrypted reads, prefix composition, both parse modes, and SecretNotFoundError on a missing secret.
A suíte de contrato compartilhada no pacote de testing roda todas as garantias portáveis contra ele — leituras descriptografadas, composição de prefix, os dois modos de parse, e SecretNotFoundError num segredo ausente.
client = create_secret_client( CreateSecretClientConfig( provider="gcp-secret-manager", env="prod", logger=my_logger, # .debug(message, context) options=GcpSecretManagerProviderOptions( project_id="my-project", ), ) )
const client = await createSecretClient({ provider: SecretProvider.GcpSecretManager, env: 'prod', logger: { debug: (message, context) => myLogger.debug(message, context), }, options: { projectId: 'my-project' }, });
create_secret_client( CreateSecretClientConfig( provider="my-vault", provider_class=MyVaultClient, ) )
await createSecretClient({ provider: 'my-vault', providerClass: MyVaultClient, });
Changelog
Changelog
Early, and honest about it. Each implementation releases on its own, so this follows the language you picked above. Within one release every distribution shares a version.
No começo, e honesto sobre isso. Cada implementação lança por conta própria, então isto acompanha a linguagem escolhida acima. Dentro de um release, toda distribuição compartilha a versão.
Added
Adicionado
get_secret accepts an env that replaces the client's environment for one call. It is never implicit and never a default: the environment the client was built with applies unless a call says otherwise, in that call alone, and omit_env still wins over it.
get_secret aceita um env que substitui o ambiente do client por uma chamada. Nunca é implícito nem default: o ambiente com que o client foi construído vale a menos que uma chamada diga o contrário, e só naquela chamada, e o omit_env continua vencendo.
Changed
Alterado
- The API reference guard now checks both directions. It asserted that every export is documented and never that every documented name still exists, so a name that left the public surface stayed in the reference indefinitely.
- The integration suites hand credentials to the provider instead of expecting them in the environment, the same way an application injects configuration — which also exercises the documented precedence of explicit credentials over the SDK chain.
- O guard da referência de API agora checa nas duas direções. Ele afirmava que todo export está documentado e nunca que todo nome documentado ainda existe, então um nome que saiu da superfície pública ficava na referência indefinidamente.
- As suítes de integração passam credenciais ao provider em vez de esperá-las no ambiente, do mesmo jeito que uma aplicação injeta configuração — o que também exercita a precedência documentada de credenciais explícitas sobre a cadeia do SDK.
The contract, the shared core, the factory, the five providers and the shared contract suite. Tagged before changelog fragments were being kept, which is why there is nothing itemised here.
O contrato, o core compartilhado, a factory, os cinco providers e a suíte de contrato compartilhada. Tagueado antes de os fragmentos de changelog começarem a ser mantidos, e é por isso que não há itens detalhados aqui.
Added
Adicionado
getSecret accepts an env that replaces the client's environment for one call. It is never implicit and never a default: the environment the client was built with applies unless a call says otherwise, in that call alone, and omitEnv still wins over it.
getSecret aceita um env que substitui o ambiente do client por uma chamada. Nunca é implícito nem default: o ambiente com que o client foi construído vale a menos que uma chamada diga o contrário, e só naquela chamada, e o omitEnv continua vencendo.
The contract, the shared core, the factory, the five providers and the shared contract suite. Tagged and feature-complete against the same contract, but nothing was pushed to npm — read it from the repository until it is.
O contrato, o core compartilhado, a factory, os cinco providers e a suíte de contrato compartilhada. Tagueado e completo em features contra o mesmo contrato, mas nada foi enviado ao npm — leia direto do repositório até que seja.