Replace playground examples
This commit is contained in:
@@ -1,173 +1,323 @@
|
|||||||
export const playgroundExamples = [
|
export const playgroundExamples = [
|
||||||
{
|
{
|
||||||
id: 'service-deployment',
|
id: 'product-api-production',
|
||||||
title: 'Service deployment',
|
title: 'Production API deployment',
|
||||||
activePath: 'main.dcdl',
|
activePath: 'main.dcdl',
|
||||||
files: {
|
files: {
|
||||||
'main.dcdl': `let
|
'main.dcdl': `let
|
||||||
schema = import "./schemas/service.dcdl";
|
schema = import "./schemas/service.dcdl";
|
||||||
prod = import "./env/prod.dcdl";
|
env = import "./env/production.dcdl";
|
||||||
shared = import "./shared/tags.dcdl";
|
org = import "./org/platform.dcdl";
|
||||||
|
release = import "./release.dcdl";
|
||||||
in
|
in
|
||||||
schema.Service & prod.ServicePatch & {
|
schema.Service & env.Production & {
|
||||||
name = "api";
|
name = "checkout-api";
|
||||||
image = "registry.example.com/api:2026-06-24";
|
image = release.image;
|
||||||
port = 9000 + 443;
|
owner = org.teams.checkout;
|
||||||
public = prod.is_public && 9000 + 443 > 9000;
|
port = 8443;
|
||||||
tags = shared.common ++ ["api", "edge"];
|
replicas = env.capacity.base_replicas + 2;
|
||||||
|
resources.cpu_milli = env.capacity.cpu_milli;
|
||||||
|
resources.memory_mb = env.capacity.memory_mb;
|
||||||
|
autoscaling.enabled = true;
|
||||||
|
autoscaling.min = env.capacity.base_replicas;
|
||||||
|
autoscaling.max = env.capacity.base_replicas * 4;
|
||||||
|
rollout.strategy = match release.risk {
|
||||||
|
"high": "canary";
|
||||||
|
"medium": "rolling";
|
||||||
|
_: "all-at-once";
|
||||||
|
};
|
||||||
|
rollout.canary_percent = match release.risk {
|
||||||
|
"high": 10;
|
||||||
|
_: 100;
|
||||||
|
};
|
||||||
|
ingress.hosts = env.domains.public ++ ["checkout.internal.example.com"];
|
||||||
|
labels = org.common_labels ++ ["service:checkout", "tier:edge"];
|
||||||
|
alerts.pager = org.pagers.checkout;
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
'schemas/service.dcdl': `Service = {
|
'schemas/service.dcdl': `Service = {
|
||||||
name = String;
|
name = String;
|
||||||
image = String;
|
image = String;
|
||||||
port = Int & > 443 default 8443;
|
owner = String;
|
||||||
|
port = Int & >= 1024 & <= 65535 default 8080;
|
||||||
replicas = Int & > 0 default 2;
|
replicas = Int & > 0 default 2;
|
||||||
public = Bool default false;
|
resources.cpu_milli = Int & >= 100 default 500;
|
||||||
feature.metrics = Bool default true;
|
resources.memory_mb = Int & >= 128 default 512;
|
||||||
feature.tracing = Bool default false;
|
autoscaling.enabled = Bool default false;
|
||||||
|
autoscaling.min = Int & > 0 default 2;
|
||||||
|
autoscaling.max = Int & > 0 default 4;
|
||||||
|
rollout.strategy = String default "rolling";
|
||||||
|
rollout.canary_percent = Int & >= 0 & <= 100 default 100;
|
||||||
|
observability.metrics = Bool default true;
|
||||||
|
observability.tracing = Bool default true;
|
||||||
|
observability.logs = Bool default true;
|
||||||
|
network.public = Bool default false;
|
||||||
};
|
};
|
||||||
`,
|
`,
|
||||||
'env/prod.dcdl': `is_public = true;
|
'env/production.dcdl': `capacity = {
|
||||||
|
base_replicas = 6;
|
||||||
|
cpu_milli = 2000;
|
||||||
|
memory_mb = 4096;
|
||||||
|
};
|
||||||
|
|
||||||
ServicePatch = {
|
domains.public = ["checkout.example.com", "api.example.com"];
|
||||||
replicas = 3;
|
|
||||||
feature.tracing = true;
|
Production = {
|
||||||
|
network.public = true;
|
||||||
|
observability.tracing = true;
|
||||||
|
observability.logs = true;
|
||||||
};
|
};
|
||||||
`,
|
`,
|
||||||
'shared/tags.dcdl': `common = ["decodal", "prod"];
|
'org/platform.dcdl': `teams = {
|
||||||
|
checkout = "team:checkout-platform";
|
||||||
|
platform = "team:core-platform";
|
||||||
|
};
|
||||||
|
|
||||||
|
pagers = {
|
||||||
|
checkout = "pagerduty:checkout-primary";
|
||||||
|
};
|
||||||
|
|
||||||
|
common_labels = ["managed-by:decodal", "environment:production"];
|
||||||
|
`,
|
||||||
|
'release.dcdl': `version = "2026.06.15";
|
||||||
|
risk = "high";
|
||||||
|
image = "registry.example.com/checkout-api:2026.06.15";
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'access-policy',
|
id: 'tenant-enterprise-plan',
|
||||||
title: 'Access policy',
|
title: 'Enterprise tenant contract',
|
||||||
activePath: 'main.dcdl',
|
activePath: 'main.dcdl',
|
||||||
files: {
|
files: {
|
||||||
'main.dcdl': `let
|
'main.dcdl': `let
|
||||||
policy = import "./policy/base.dcdl";
|
schema = import "./schemas/tenant.dcdl";
|
||||||
teams = import "./policy/teams.dcdl";
|
plans = import "./plans.dcdl";
|
||||||
env = "prod";
|
region = import "./regions/eu.dcdl";
|
||||||
|
customer = import "./customers/acme.dcdl";
|
||||||
in
|
in
|
||||||
{
|
schema.Tenant & (plans.Enterprise // region.Europe // customer.Acme // {
|
||||||
service = "payments";
|
slug = "acme";
|
||||||
readers = policy.defaultReaders ++ teams.observability;
|
display_name = "Acme Manufacturing";
|
||||||
writers = policy.defaultWriters ++ teams.payments;
|
limits.users = customer.seats + 25;
|
||||||
admins = match env {
|
limits.projects = 200;
|
||||||
"prod": policy.breakglassAdmins;
|
limits.storage_gb = 2048;
|
||||||
_: teams.platform;
|
features.audit_log = true;
|
||||||
|
features.sso = true;
|
||||||
|
features.data_residency = true;
|
||||||
|
compliance.retention_days = match customer.contract_tier {
|
||||||
|
"regulated": 2555;
|
||||||
|
_: 365;
|
||||||
};
|
};
|
||||||
audit.required = env == "prod";
|
notifications.channels = customer.notification_channels ++ ["security"];
|
||||||
audit.retention_days = match env {
|
})
|
||||||
"prod": 365;
|
`,
|
||||||
_: 30;
|
'schemas/tenant.dcdl': `Tenant = {
|
||||||
|
slug = String;
|
||||||
|
display_name = String;
|
||||||
|
plan = String default "standard";
|
||||||
|
limits.users = Int & > 0 default 25;
|
||||||
|
limits.projects = Int & > 0 default 20;
|
||||||
|
limits.storage_gb = Int & > 0 default 100;
|
||||||
|
features.sso = Bool default false;
|
||||||
|
features.audit_log = Bool default true;
|
||||||
|
features.data_residency = Bool default false;
|
||||||
|
compliance.region = String default "us";
|
||||||
|
compliance.retention_days = Int & >= 30 default 90;
|
||||||
|
billing.currency = String default "USD";
|
||||||
|
billing.invoice_day = Int & >= 1 & <= 28 default 1;
|
||||||
};
|
};
|
||||||
}
|
|
||||||
`,
|
`,
|
||||||
'policy/base.dcdl': `defaultReaders = ["group:engineering", "group:support"];
|
'plans.dcdl': `Enterprise = {
|
||||||
defaultWriters = ["group:platform"];
|
plan = "enterprise";
|
||||||
breakglassAdmins = ["user:oncall-primary", "user:oncall-secondary"];
|
limits.users = 500;
|
||||||
|
limits.projects = 100;
|
||||||
|
limits.storage_gb = 1024;
|
||||||
|
features.sso = true;
|
||||||
|
features.audit_log = true;
|
||||||
|
billing.invoice_day = 15;
|
||||||
|
};
|
||||||
`,
|
`,
|
||||||
'policy/teams.dcdl': `platform = ["group:platform-admins"];
|
'regions/eu.dcdl': `Europe = {
|
||||||
payments = ["group:payments-api", "group:payments-sre"];
|
compliance.region = "eu-west";
|
||||||
observability = ["group:observability"];
|
compliance.retention_days = 365;
|
||||||
|
billing.currency = "EUR";
|
||||||
|
};
|
||||||
|
`,
|
||||||
|
'customers/acme.dcdl': `seats = 475;
|
||||||
|
contract_tier = "regulated";
|
||||||
|
notification_channels = ["email", "slack", "pagerduty"];
|
||||||
|
|
||||||
|
Acme = {
|
||||||
|
billing.invoice_day = 10;
|
||||||
|
};
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'edge-worker',
|
id: 'event-pipeline-prod',
|
||||||
title: 'Edge worker config',
|
title: 'Event ingestion pipeline',
|
||||||
activePath: 'main.dcdl',
|
|
||||||
files: {
|
|
||||||
'main.dcdl': `let
|
|
||||||
schema = import "./schemas/worker.dcdl";
|
|
||||||
routes = import "./routes.dcdl";
|
|
||||||
production = true;
|
|
||||||
in
|
|
||||||
schema.Worker & {
|
|
||||||
name = "decodal-docs";
|
|
||||||
compatibility_date = "2026-06-15";
|
|
||||||
workers_dev = !production;
|
|
||||||
route.host = routes.primary_host;
|
|
||||||
route.paths = routes.docs_paths ++ routes.playground_paths;
|
|
||||||
cache.ttl_seconds = 60 * 60;
|
|
||||||
cache.bypass = !production;
|
|
||||||
}
|
|
||||||
`,
|
|
||||||
'schemas/worker.dcdl': `Worker = {
|
|
||||||
name = String;
|
|
||||||
compatibility_date = String;
|
|
||||||
workers_dev = Bool default false;
|
|
||||||
route.host = String;
|
|
||||||
cache.ttl_seconds = Int & >= 0 default 300;
|
|
||||||
cache.bypass = Bool default false;
|
|
||||||
};
|
|
||||||
`,
|
|
||||||
'routes.dcdl': `primary_host = "decodal.example.com";
|
|
||||||
docs_paths = ["/docs/*", "/assets/*"];
|
|
||||||
playground_paths = ["/playground/*"];
|
|
||||||
`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'data-pipeline',
|
|
||||||
title: 'Data pipeline',
|
|
||||||
activePath: 'main.dcdl',
|
activePath: 'main.dcdl',
|
||||||
files: {
|
files: {
|
||||||
'main.dcdl': `let
|
'main.dcdl': `let
|
||||||
schema = import "./schemas/pipeline.dcdl";
|
schema = import "./schemas/pipeline.dcdl";
|
||||||
presets = import "./presets/batch.dcdl";
|
env = import "./env/prod.dcdl";
|
||||||
env = "staging";
|
sources = import "./sources/events.dcdl";
|
||||||
|
sinks = import "./sinks/warehouse.dcdl";
|
||||||
|
transforms = import "./transforms.dcdl";
|
||||||
in
|
in
|
||||||
schema.Pipeline & presets.Batch & {
|
schema.Pipeline & env.Production & {
|
||||||
name = "events-rollup";
|
name = "events-rollup";
|
||||||
source.topic = "events.raw";
|
source.kafka_cluster = sources.cluster;
|
||||||
sink.table = "analytics.events_daily";
|
source.topic = sources.raw_topic;
|
||||||
workers = match env {
|
source.consumer_group = "analytics-events-rollup";
|
||||||
"prod": 8;
|
sink.table = sinks.daily_events_table;
|
||||||
"staging": 3;
|
sink.mode = "append";
|
||||||
_: 1;
|
workers = env.scale.worker_count;
|
||||||
|
batch.size = env.scale.batch_size;
|
||||||
|
batch.timeout_seconds = 60 + 30;
|
||||||
|
schedule.cron = "*/15 * * * *";
|
||||||
|
transforms = transforms.standard ++ transforms.privacy ++ ["aggregate_daily"];
|
||||||
|
quality.max_lag_seconds = match env.tier {
|
||||||
|
"gold": 120;
|
||||||
|
"silver": 300;
|
||||||
|
_: 900;
|
||||||
};
|
};
|
||||||
alerts.enabled = env != "dev";
|
alerts.channels = env.alert_channels;
|
||||||
transforms = presets.standardTransforms ++ ["dedupe", "aggregate_daily"];
|
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
'schemas/pipeline.dcdl': `Pipeline = {
|
'schemas/pipeline.dcdl': `Pipeline = {
|
||||||
name = String;
|
name = String;
|
||||||
|
source.kafka_cluster = String;
|
||||||
source.topic = String;
|
source.topic = String;
|
||||||
|
source.consumer_group = String;
|
||||||
sink.table = String;
|
sink.table = String;
|
||||||
workers = Int & > 0 default 1;
|
sink.mode = String default "append";
|
||||||
|
workers = Int & > 0 default 2;
|
||||||
batch.size = Int & >= 100 default 1000;
|
batch.size = Int & >= 100 default 1000;
|
||||||
batch.timeout_seconds = Int & > 0 default 60;
|
batch.timeout_seconds = Int & > 0 default 60;
|
||||||
alerts.enabled = Bool default false;
|
schedule.cron = String;
|
||||||
|
quality.max_lag_seconds = Int & > 0 default 300;
|
||||||
|
dead_letter.enabled = Bool default true;
|
||||||
|
dead_letter.topic = String default "events.dead_letter";
|
||||||
};
|
};
|
||||||
`,
|
`,
|
||||||
'presets/batch.dcdl': `standardTransforms = ["parse_json", "validate_schema", "enrich_metadata"];
|
'env/prod.dcdl': `tier = "gold";
|
||||||
|
alert_channels = ["slack:data-platform", "pagerduty:data-primary"];
|
||||||
|
|
||||||
Batch = {
|
scale = {
|
||||||
batch.size = 5000;
|
worker_count = 12;
|
||||||
batch.timeout_seconds = 30 + 30;
|
batch_size = 5000;
|
||||||
|
};
|
||||||
|
|
||||||
|
Production = {
|
||||||
|
dead_letter.enabled = true;
|
||||||
|
};
|
||||||
|
`,
|
||||||
|
'sources/events.dcdl': `cluster = "kafka-prod-use1";
|
||||||
|
raw_topic = "events.raw.v3";
|
||||||
|
`,
|
||||||
|
'sinks/warehouse.dcdl': `daily_events_table = "analytics.events_daily";
|
||||||
|
`,
|
||||||
|
'transforms.dcdl': `standard = ["parse_json", "validate_schema", "dedupe"];
|
||||||
|
privacy = ["redact_ip", "hash_user_id"];
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'edge-cdn-policy',
|
||||||
|
title: 'Edge CDN routing policy',
|
||||||
|
activePath: 'main.dcdl',
|
||||||
|
files: {
|
||||||
|
'main.dcdl': `let
|
||||||
|
schema = import "./schemas/edge.dcdl";
|
||||||
|
domains = import "./domains.dcdl";
|
||||||
|
security = import "./security.dcdl";
|
||||||
|
env = "production";
|
||||||
|
in
|
||||||
|
schema.EdgeApplication & security.StrictHeaders & {
|
||||||
|
name = "docs-and-playground";
|
||||||
|
domains = domains.primary ++ domains.aliases;
|
||||||
|
origin.host = "origin-docs.internal.example.com";
|
||||||
|
origin.port = 443;
|
||||||
|
tls.mode = "strict";
|
||||||
|
cache.default_ttl_seconds = 60 * 60;
|
||||||
|
cache.static_ttl_seconds = 60 * 60 * 24;
|
||||||
|
cache.bypass_preview = env != "production";
|
||||||
|
routing.docs_paths = ["/docs/*", "/assets/*"];
|
||||||
|
routing.playground_paths = ["/playground/*"];
|
||||||
|
waf.enabled = true;
|
||||||
|
waf.rules = security.managed_rules ++ ["block-country:kp", "rate-limit-login"];
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
'schemas/edge.dcdl': `EdgeApplication = {
|
||||||
|
name = String;
|
||||||
|
origin.host = String;
|
||||||
|
origin.port = Int & >= 1 & <= 65535 default 443;
|
||||||
|
tls.mode = String default "strict";
|
||||||
|
cache.default_ttl_seconds = Int & >= 0 default 300;
|
||||||
|
cache.static_ttl_seconds = Int & >= 0 default 86400;
|
||||||
|
cache.bypass_preview = Bool default false;
|
||||||
|
waf.enabled = Bool default true;
|
||||||
|
};
|
||||||
|
`,
|
||||||
|
'domains.dcdl': `primary = ["decodal.example.com"];
|
||||||
|
aliases = ["www.decodal.example.com", "docs.decodal.example.com"];
|
||||||
|
`,
|
||||||
|
'security.dcdl': `managed_rules = ["owasp-core", "known-bots", "credential-stuffing"];
|
||||||
|
|
||||||
|
StrictHeaders = {
|
||||||
|
headers.hsts = "max-age=31536000; includeSubDomains; preload";
|
||||||
|
headers.referrer_policy = "same-origin";
|
||||||
|
headers.frame_options = "DENY";
|
||||||
};
|
};
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'diagnostics',
|
id: 'incident-escalation',
|
||||||
title: 'Diagnostics: invalid port',
|
title: 'Incident escalation policy',
|
||||||
activePath: 'main.dcdl',
|
activePath: 'main.dcdl',
|
||||||
files: {
|
files: {
|
||||||
'main.dcdl': `let
|
'main.dcdl': `let
|
||||||
schema = import "./schemas/service.dcdl";
|
schema = import "./schemas/oncall.dcdl";
|
||||||
|
teams = import "./teams.dcdl";
|
||||||
|
calendar = import "./calendar.dcdl";
|
||||||
|
severity = "sev1";
|
||||||
in
|
in
|
||||||
schema.Service & {
|
schema.Policy & {
|
||||||
name = "broken-api";
|
service = "payments";
|
||||||
port = 442;
|
severity = severity;
|
||||||
|
primary = teams.payments_primary;
|
||||||
|
secondary = teams.platform_secondary;
|
||||||
|
notify = teams.payments_primary ++ teams.platform_secondary ++ calendar.executive_watch;
|
||||||
|
response_minutes = match severity {
|
||||||
|
"sev1": 5;
|
||||||
|
"sev2": 15;
|
||||||
|
_: 60;
|
||||||
|
};
|
||||||
|
escalation.after_minutes = match severity {
|
||||||
|
"sev1": 10;
|
||||||
|
"sev2": 30;
|
||||||
|
_: 120;
|
||||||
|
};
|
||||||
|
escalation.targets = teams.platform_secondary ++ calendar.executive_watch;
|
||||||
|
runbooks = ["runbooks/payments-api", "runbooks/database-failover"];
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
'schemas/service.dcdl': `Service = {
|
'schemas/oncall.dcdl': `Policy = {
|
||||||
name = String;
|
service = String;
|
||||||
port = Int & > 443 default 8443;
|
severity = String;
|
||||||
replicas = Int & > 0 default 2;
|
response_minutes = Int & > 0 default 30;
|
||||||
|
escalation.after_minutes = Int & > 0 default 60;
|
||||||
|
auto_page = Bool default true;
|
||||||
|
create_status_page = Bool default true;
|
||||||
};
|
};
|
||||||
|
`,
|
||||||
|
'teams.dcdl': `payments_primary = ["user:pay-oncall-a", "user:pay-oncall-b"];
|
||||||
|
platform_secondary = ["user:platform-sre-a", "user:platform-sre-b"];
|
||||||
|
`,
|
||||||
|
'calendar.dcdl': `executive_watch = ["user:vp-engineering", "user:cto"];
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user