From 8eda660956787336570e54880fbadd0bafbfbb9e Mon Sep 17 00:00:00 2001 From: Sebastian Tiedtke Date: Tue, 26 Mar 2024 09:06:23 -0400 Subject: [PATCH] Use text examples --- internal/owl/README.md | 72 +++++++++++++++++++++++++++--------- internal/owl/front-end.png | Bin 6954 -> 0 bytes internal/owl/resolution.png | Bin 16102 -> 0 bytes 3 files changed, 55 insertions(+), 17 deletions(-) delete mode 100644 internal/owl/front-end.png delete mode 100644 internal/owl/resolution.png diff --git a/internal/owl/README.md b/internal/owl/README.md index cee0dbeac..25de5b88b 100644 --- a/internal/owl/README.md +++ b/internal/owl/README.md @@ -6,34 +6,37 @@ version = 'v3' # The Owl Store 🦉 -What is it? +### What is it? + +![Owl Store](owl.png) ## A ENV solution for Humans **and** Workloads: + - Specify, Validate, and Resolve ENV vars - Verification of “Correctness” & better tools ## Took inspiration from + - The SSH-Agent - How Typescript brings type-safety to Javascript ## Why? + - Make idea of “SSO for your Environments” come to live - The 🦉 knows best, because she's the wisest of birds in the animal kingdom -![Owl Store](owl.png) - ## Environment “Specs” The **.env.example** frontend/facade: -```ini {"id":"01HS8C1PN0T7BGJA0T6TT2G68R"} - JWT_SECRET=Secret to sign authed JWT tokens # Secret! - ANON_KEY=Secret to sign anonymous JWT tokens # Secret! - SERVICE_ROLE_KEY=JWT to assume the service role # JWT - POSTGRES_PASSWORD=Password for the postgres user # Password! - DASHBOARD_USERNAME=Username for the dashboard # Plain! - DASHBOARD_PASSWORD=Password for the dashboard # Password! - SOME_OTHER_VAR=Needs a matching value # Regex(/^[a-z...a. -]+\.) +```ini {"id":"01HS8C1PN0T7BGJA0T6TT2G68R","interpreter":"cat"} +JWT_SECRET=Secret to sign authed JWT tokens # Secret! +ANON_KEY=Secret to sign anonymous JWT tokens # Secret! +SERVICE_ROLE_KEY=JWT to assume the service role # JWT +POSTGRES_PASSWORD=Password for the postgres user # Password! +DASHBOARD_USERNAME=Username for the dashboard # Plain! +DASHBOARD_PASSWORD=Password for the dashboard # Password! +SOME_OTHER_VAR=Needs a matching value # Regex(/^[a-z...a. -]+\.) ``` ### Philosophy @@ -56,13 +59,48 @@ The **.env.example** frontend/facade: ## Extensible at every stage -#### Resolution (e.g. translated env.owl.yaml or JS/Golang/Java/etc SDKs) - -![resolution](resolution.png) - -#### .env Front-end (query ASTs rendered in text for illustration) +#### Resolution (e.g. translated `env.owl.yaml` or JS/Golang/Java/etc SDKs) + +```graphql {"id":"01HSXDJ4HAGVVT62961TK2NTBT","interpreter":"cat"} +query ResolveEnv(...) { + ... + render { + withCell(ulid: "01HRA297WC2HJP7X48FM3DR1V0") { + withShell(command: "terraform output -json | jq -r .workspace_vars.value.{}") { + command + withWebhook(url: "https://secrets.platform.runme.dev/resolver") { + url + withStateful(org: "acme-corp") { + org + dotenv(prefix: "VITE_REACT_APP_", export: false) + snapshot { + ... + } + } + } + } + } + } +} +``` -![front-end](front-end.png) +#### .env-Frontend (query ASTs rendered in text for illustration) + +```graphql {"id":"01HSXDR2PDVFZ9ZV8Z60XK6MTB","interpreter":"cat"} +query LoadDotEnvs { + process { + path + file(paths: ["env.spec", ".env.example"], ignoreSpecs: false) { + path + file(paths: [".env.local", ".env"]) { + path + vars + specs + } + } + } +} +``` ## Common set of Specs (not all available yet) diff --git a/internal/owl/front-end.png b/internal/owl/front-end.png deleted file mode 100644 index f021708f51711eb3be0942c1371d21d2f91cae4c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6954 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