Skip to content

Roadmap

Internal tracking doc - improvements, new providers, and the path to a publishable NPM package.


Tech Debt

  • [x] config/default.sh is superseded by config/default.yaml - can be removed once Ansible is confirmed as the standard
  • [x] LoadBalancerBuilder (DO) does not extend BaseBuilder - inconsistent lifecycle, uses Config.isGlobalDryRun() instead of isDryRunActive(), no sidecar/protection support
  • [x] DO DomainBuilder deletes and recreates records on every deploy instead of true upsert - can cause brief DNS gaps
  • [x] Firebase FunctionsBuilder skips eager discovery (resolves null immediately) - diverges from the standard pattern where discovery fires in the constructor
  • [x] Scattered as any casts on Route53 record types and elsewhere - replace with proper SDK type imports where possible
  • [x] DropletBuilder.sslKey() method named incorrectly - all other providers use .sshKey(); renamed to .sshKey() with a deprecated .sslKey() shim for backwards compatibility

Testing

  • [x] Basic test suite (core: config.test.ts, output.test.ts)
  • [x] Provider unit tests with mocked API clients - each builder's deploy() and destroy() paths covered (create, skip, update, dry-run) (DO, AWS S3/Route53/Lambda, and Firebase Hosting/Functions fully complete)
  • [x] Dry-run integration tests - run full stacks with dryRun: true against real provider credentials to verify discovery without writing
  • [x] CI pipeline - run unit tests on every push; dry-run suite on PRs that touch provider code
  • [x] End-to-end tests against sandboxes (LocalStack for AWS, DO staging token, Firebase emulator)

Provider Improvements

Proxmox

  • [x] Cluster-aware node selection - pick the node with the most free RAM via /nodes API instead of always using the first configured node
  • [x] .machine() builder method - let users override machine type (i440fx vs q35) per VM rather than the hardcoded default
  • [x] CONFIG.PRODUCTION entry in src/types/proxmox.ts
  • [x] Golden Image / VM Templates (Proxmox.Template) - Declare pre-baked templates with fluent OS base images and playbook provisioning (Packer-like behavior). Clone VMs from these templates to drop VM deployment time from minutes to seconds.

AWS

  • [x] CloudFront cache invalidation - .invalidate(paths[]) on a CloudFront builder
  • [x] S3 file upload - .upload(filePath) uploads a single file to the bucket on deploy
  • [x] Route53 record types - A, AAAA, CNAME, MX, TXT, NS, PTR, SRV, CAA, NAPTR, SPF via .record(); per-record TTL; TXT auto-quoting
  • [x] S3 static site hosting - .staticSite() sets index/error documents and public-read policy
  • [x] IAM - role and inline/managed policy management; useful for cross-service wiring without manual console steps
  • [x] CloudWatch alarms - CPU/memory thresholds on Fargate and RDS with SNS notification target
  • [x] EC2 - Provision EC2 virtual machines with VPC/SG support and stateless tag-based playbook provisioning.
  • [x] Golden Image / VM Templates (AWS.Template) - Declare pre-baked custom AMIs with fluent OS base images and playbook provisioning (Packer-like behavior). Clone EC2 instances from these templates to drop VM deployment time from minutes to seconds.

DigitalOcean

  • [x] Droplet, Domain, Firewall, Certificate, LoadBalancer
  • [x] LoadBalancerBuilder overhaul - extend BaseBuilder, add .region(), .healthCheck(), .stickySession(), configurable forwarding rules and SSL termination
  • [x] Spaces - S3-compatible object storage; .bucket(), .cors(), .acl()
  • [x] Managed databases - Postgres, MySQL, Redis; analogous to AWS RDS
  • [x] App Platform - deploy from a GitHub repo or container image without managing Droplets
  • [x] VPC - create and assign Droplets/databases to a private network
  • [x] Domain: add AAAA, SRV, CAA record types; implement destroy() for domain and records

Firebase

  • [x] Firebase Hosting - deploy a web app from a local build directory; file-level caching via SHA256
  • [x] Firebase Functions - deploy Cloud Functions v2 from source; full create/update/delete lifecycle
  • [x] Firebase Firestore - rules deployment and composite index management
  • [x] Firebase Auth - email/password, anonymous, phone, and OAuth providers (Google, GitHub, Facebook, Twitter, Apple, Microsoft); authorized domains
  • [x] Firebase Storage - rules deployment, CORS configuration, lifecycle policies
  • [x] Firebase RemoteConfig - typed parameters (string, bool, number, JSON), conditions, and per-condition overrides; ETag-safe PUT
  • [x] Firebase App Check - enforce attestation on Hosting, Functions, and Firestore

Google Cloud Platform (GCP)

  • [x] GCP Cloud Run (GCP.CloudRun) - Deploy containerized services with auto-scaling and public URLs (Fargate parity)
  • [x] GCP Cloud SQL (GCP.CloudSQL) - Managed PostgreSQL and MySQL database instances (RDS parity)
  • [x] GCP Secret Manager (GCP.Secret) - Manage and inject GCP secrets at deploy-time (SecretsManager parity)
  • [x] GCP Pub/Sub (GCP.PubSub) - Topics and subscriptions for decoupled messaging (SQS/SNS parity)
  • [x] GCP Cloud DNS (GCP.CloudDNS) - Managed zones, record sets, and DNS routing (Route53 parity)
  • [x] GCP IAM (GCP.ServiceAccount / GCP.IAMBinding) - Service accounts, custom roles, and resource-level IAM bindings (IAM parity)
  • [x] GCP Compute VM (GCP.VM) - Compute instances with external IP NAT and universal playbook provisioning (EC2/Proxmox parity)
  • [x] Golden Image / VM Templates (GCP.Template) - Declare pre-baked GCP custom images with fluent OS base images and playbook provisioning (Packer-like behavior). Clone Compute VMs from these templates to drop VM deployment time from minutes to seconds.

New Providers

Cloudflare

Strong candidate for a first-class provider - widely used alongside or instead of AWS for DNS and CDN, and the API is clean.

@Deploy({ cloudflare: { token: process.env.CF_TOKEN } })
class EdgeStack extends Stack {
  zone   = CF.Zone("example.com");
  worker = CF.Worker("api").script("./workers/api").route("api.example.com/*");
  kv     = CF.KV("sessions");
  r2     = CF.R2("assets");
}
  • [x] Zone + DNS - hosted zone discovery, full record type support (mirrors Route53 implementation)
  • [x] Workers - deploy a Worker script with routes and env bindings
  • [x] KV - key-value namespace management
  • [x] R2 - S3-compatible object storage; useful as a cheaper CloudFront+S3 alternative
  • [x] Pages - static site hosting with preview deployments

Hetzner Cloud

Popular self-hosting alternative to DigitalOcean - similar API shape, easy to add.

  • [x] Server - analogous to DO Droplet; image, type, location, SSH key
  • [x] Network / VPC - private networking between servers
  • [x] Firewall - inbound/outbound rules
  • [x] Load Balancer - HTTP/HTTPS with health checks
  • [x] Volume - persistent block storage attached to servers

Vultr

Excellent global footprint with high-performance compute, bare-metal options, and GPU cloud support.

  • [ ] Instance - Cloud compute VPS instances (regular and high-frequency)
  • [ ] Bare Metal - Dedicated physical servers provisioned via API
  • [ ] VPC / Network - Private network boundaries (VPC 2.0)
  • [ ] Block Storage - SSD-backed volumes attached to instances
  • [ ] Firewall - Group-based access control rules

Microsoft Azure

Enterprise cloud provider - critical for corporate environments. Needs resource group management, VM provisioning, and active directory support.

  • [x] Resource Groups - basic resource lifecycle boundary
  • [x] Azure App Service (Azure.AppService) - PaaS web app provisioning with slots support
  • [x] Azure Virtual Machines (Azure.VM) - Compute instances with private virtual network support and universal playbook provisioning
  • [x] Azure SQL Database (Azure.SQL) - Managed databases with automated failover groups
  • [x] Azure Blob Storage (Azure.BlobStorage) - Massively scalable object storage

Akamai

Enterprise CDN/edge - complex enough to warrant a dedicated maintainer; community-driven.


NPM Package

  • [x] Switch package.json to "type": "module" (ESM)
  • [x] Basic test suite
  • [x] Add "exports" map with per-provider sub-paths so consumers can import only what they need (e.g. puls-dev/aws, puls-dev/firebase)
  • [x] Ship compiled JS + .d.ts declarations
  • [x] Standard dependencies for zero-friction out-of-the-box pre-1.0 install
  • [x] Scoped Monorepo Sub-Packages - Split puls-dev into separate scoped packages published to the registry (@puls-dev/core, @puls-dev/aws, @puls-dev/gcp, etc.) to provide zero-friction installs with zero dependency bloat
  • [ ] Semver versioning - provider additions = minor, breaking DSL changes = major

Framework Features

  • [x] Stack outputs - pass Output<T> values between stacks; eager resolution unblocks dependents automatically
  • [x] Inventory / @Check - read-only discovery across all configured providers; prints counts, status, and DO cost estimates
  • [x] Dry run - dryRun: true or @DryRun prints a full plan without any API writes
  • [x] @Protected - marks a resource so it is never modified or destroyed
  • [x] Idempotent Configuration State Tracking - Store applied playbook and file hashes directly in VM metadata (e.g. Proxmox notes/tags) to support stateless, change-aware Ansible configuration updates on already created servers
  • [x] Hooks - beforeDeploy / afterDeploy callbacks on Stack for custom side effects (notify Slack, run migrations, etc.)
  • [x] Multi-region - run the same stack across N regions in parallel; @Deploy({ regions: [REGION.EU_CENTRAL_1, REGION.US_EAST_1] })
  • [x] Parallel resource deployment - resources within a stack that have no declared dependency could deploy concurrently instead of sequentially
  • [x] Secrets at deploy time - pull credentials from AWS SSM Parameter Store or HashiCorp Vault instead of requiring them as env vars upfront
  • [x] Hybrid Resource Configuration (YAML) - Support loading bulk static configuration sets (like DNS records, firewall rules, or security group rules) directly from a .yaml or .json file within builder methods while retaining the flexibility to chain programmatic methods for dynamic resource parameters.
  • [x] Opt-in Infrastructure Blueprint Documentation (Config.blueprint) - Generate version-controlled markdown blueprints (docs/architecture.md) of live system resources, auto-calculating monthly costs, formatting live endpoints, and rendering Mermaid.js dynamic dependency/topology graphs on local runs.
  • [x] Multi-account & Multi-tenant Contexts - Dynamic or context-bound provider credentials in Stacks
  • [x] Eager Cost Estimation - Estimate monthly infrastructure cost shifts directly in puls diff/puls plan
  • [x] Policy-as-Code Guardrails - Enforce declarative pre-deploy compliance policies in pure TypeScript
  • [x] Implicit Dependency Resolution via Output Interpolation - GCP.BigQueryView.query() accepts template-literal-interpolated view builders; sentinels auto-wire dependsOn and resolve to qualified refs (`project.dataset.view`) at deploy time

Roadmap Gap Analysis (Tech Debt / Planned Improvements)

A version-controlled analysis of internal tech debt and feature gaps. Gaps are addressed opportunistically.

  • [x] Gap 1: Output Not Exported - Output<T> is missing from public API index in src/index.ts. Resolving this enables clean public imports for developer-built custom types and cross-stack variables.
  • [x] Gap 2: Generic Retry & Backoff Engine - Implement a shared withRetry or exponential backoff utility across all providers to handle transient network/API throttling errors gracefully under heavy parallel deployments.
  • [x] Gap 3: Resource Import & Adoption - Provide an .adoptId() mechanism on BaseBuilder to allow existing, out-of-band cloud infrastructure to be safely imported under Puls management without recreation.
  • [x] Gap 4: Shell Script Provisioning Deprecation - Explicitly document the deprecation of .sh script provisioning (in favor of Ansible/Puppet playbooks) to avoid user migration confusion.
  • [x] Gap 5: Advanced Drift Detection & diff - Clarify stateless tag/note-based metadata tracking in architecture docs, and design a formal Stack.diff() structural diff engine comparing declared settings against live cloud properties.
  • [x] Gap 6: Checker Integration Completeness - Newer providers (GCP, Firebase) lack list.ts implementations, causing @Check to silently skip them. Resolve by providing complete list.ts inventory engines for GCP and Firebase.
  • [x] Gap 7: Provider Plugin & Decoupling API - Establish a standard registerProvider() hook and split core framework utilities into an independent @puls-dev/core package to enable community-built custom providers.

Breaking Changes & Migration Notes

Shell Script (.sh) Provisioning Removal

  • Change: Standard .sh shell scripts are no longer supported inside the .provision() method.
  • Rationale: Shell scripts are inherently stateful and lack change-aware, idempotent execution. Puls standardizes on Ansible playbooks (.yaml/.yml) and Puppet manifests (.pp) which record provisioning status hashes directly within live resource metadata.
  • Migration Path: Convert raw shell commands to standard Ansible tasks. For example, migrate package installation or service setup to ansible.builtin.apt or standard Ansible modules, and save them as a playbook .yaml file.