{
  "manifest_version": "1.0.0",
  "template": {
    "id": "56ef5ed9-bda6-49d1-a877-9476b8064d8c",
    "slug": "carnet-de-combat",
    "name": "carnet de combat",
    "description": "Training log for grapplers: calendar, competitions, stats and photo gallery",
    "url": "https://railway.com/deploy/carnet-de-combat",
    "upstream": {
      "repo_url": "https://github.com/ismavld/carnet-de-combat"
    }
  },
  "status": "unvalidated",
  "validated_at": null,
  "success_rate_30d": null,
  "services": [
    {
      "name": "Postgres",
      "source": {
        "image": "ghcr.io/railwayapp-templates/postgres-ssl:18"
      },
      "needs_volume": true,
      "volume_mount_path": "/var/lib/postgresql/data",
      "http": false
    },
    {
      "name": "carnet-de-combat",
      "source": {
        "repo": "https://github.com/ismavld/carnet-de-combat"
      },
      "needs_volume": false,
      "http": true
    },
    {
      "name": "function-bun",
      "source": {
        "image": "ghcr.io/railwayapp/function-bun:1.4.4"
      },
      "needs_volume": false,
      "http": true
    }
  ],
  "required_inputs": [
    {
      "key": "PGDATA",
      "service": "Postgres",
      "description": "Provide a value for PGDATA.",
      "secret": false,
      "strategy": "ask_user"
    },
    {
      "key": "PGHOST",
      "service": "Postgres",
      "description": "Provide a value for PGHOST.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_private_domain"
    },
    {
      "key": "PGPORT",
      "service": "Postgres",
      "description": "Provide a value for PGPORT.",
      "secret": false,
      "strategy": "ask_user"
    },
    {
      "key": "PGUSER",
      "service": "Postgres",
      "description": "Provide a value for PGUSER.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "PGDATABASE",
      "service": "Postgres",
      "description": "Provide a value for PGDATABASE.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "PGPASSWORD",
      "service": "Postgres",
      "description": "Provide a value for PGPASSWORD.",
      "secret": true,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "POSTGRES_DB",
      "service": "Postgres",
      "description": "Provide a value for POSTGRES_DB.",
      "secret": false,
      "strategy": "ask_user"
    },
    {
      "key": "DATABASE_URL",
      "service": "Postgres",
      "description": "Provide a value for DATABASE_URL.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_private_domain"
    },
    {
      "key": "POSTGRES_USER",
      "service": "Postgres",
      "description": "Provide a value for POSTGRES_USER.",
      "secret": false,
      "strategy": "ask_user"
    },
    {
      "key": "SSL_CERT_DAYS",
      "service": "Postgres",
      "description": "Provide a value for SSL_CERT_DAYS.",
      "secret": false,
      "strategy": "ask_user"
    },
    {
      "key": "POSTGRES_PASSWORD",
      "service": "Postgres",
      "description": "Provide a value for POSTGRES_PASSWORD.",
      "secret": true,
      "strategy": "generate",
      "generate": "strong_password"
    },
    {
      "key": "RAILWAY_DEPLOYMENT_DRAINING_SECONDS",
      "service": "Postgres",
      "description": "Provide a value for RAILWAY_DEPLOYMENT_DRAINING_SECONDS.",
      "secret": false,
      "strategy": "ask_user"
    },
    {
      "key": "APP_URL",
      "service": "carnet-de-combat",
      "description": "Provide a value for APP_URL.",
      "secret": false,
      "strategy": "ask_user"
    },
    {
      "key": "DB_HOST",
      "service": "carnet-de-combat",
      "description": "Provide a value for DB_HOST.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "DB_NAME",
      "service": "carnet-de-combat",
      "description": "Provide a value for DB_NAME.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "DB_PORT",
      "service": "carnet-de-combat",
      "description": "Provide a value for DB_PORT.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "DB_USER",
      "service": "carnet-de-combat",
      "description": "Provide a value for DB_USER.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "DB_PASSWORD",
      "service": "carnet-de-combat",
      "description": "Provide a value for DB_PASSWORD.",
      "secret": true,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "MAIL_SECRET",
      "service": "carnet-de-combat",
      "description": "Provide a value for MAIL_SECRET.",
      "secret": true,
      "strategy": "generate",
      "generate": "random_base64_32"
    },
    {
      "key": "AWS_ENDPOINT_URL",
      "service": "carnet-de-combat",
      "description": "Provide a value for AWS_ENDPOINT_URL.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "AWS_ACCESS_KEY_ID",
      "service": "carnet-de-combat",
      "description": "Provide a value for AWS_ACCESS_KEY_ID.",
      "secret": true,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "MAIL_FUNCTION_URL",
      "service": "carnet-de-combat",
      "description": "Provide a value for MAIL_FUNCTION_URL.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_private_domain"
    },
    {
      "key": "AWS_DEFAULT_REGION",
      "service": "carnet-de-combat",
      "description": "Provide a value for AWS_DEFAULT_REGION.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "AWS_S3_BUCKET_NAME",
      "service": "carnet-de-combat",
      "description": "Provide a value for AWS_S3_BUCKET_NAME.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "AWS_SECRET_ACCESS_KEY",
      "service": "carnet-de-combat",
      "description": "Provide a value for AWS_SECRET_ACCESS_KEY.",
      "secret": true,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "MAIL_SECRET",
      "service": "function-bun",
      "description": "Provide a value for MAIL_SECRET.",
      "secret": true,
      "strategy": "generate",
      "generate": "random_base64_32"
    },
    {
      "key": "RESEND_API_KEY",
      "service": "function-bun",
      "description": "Provide a value for RESEND_API_KEY.",
      "secret": true,
      "strategy": "generate",
      "generate": "random_base64_32"
    },
    {
      "key": "TEMPLATE_RESET_ID",
      "service": "function-bun",
      "description": "Provide a value for TEMPLATE_RESET_ID.",
      "secret": false,
      "strategy": "ask_user"
    },
    {
      "key": "TEMPLATE_VALIDATE_ID",
      "service": "function-bun",
      "description": "Provide a value for TEMPLATE_VALIDATE_ID.",
      "secret": false,
      "strategy": "ask_user"
    },
    {
      "key": "TEMPLATE_CHANGEMAIL_ID",
      "service": "function-bun",
      "description": "Provide a value for TEMPLATE_CHANGEMAIL_ID.",
      "secret": false,
      "strategy": "ask_user"
    },
    {
      "key": "TEMPLATE_CHANGEMAIL_ALERT_ID",
      "service": "function-bun",
      "description": "Provide a value for TEMPLATE_CHANGEMAIL_ALERT_ID.",
      "secret": false,
      "strategy": "ask_user"
    }
  ],
  "deploy": {
    "mcp": {
      "server": "railway",
      "tool": "deploy_template",
      "args": {
        "template_code": "carnet-de-combat"
      }
    },
    "cli": "railway deploy --template carnet-de-combat",
    "api": {
      "method": "POST",
      "path": "/graphql/v2",
      "body": {
        "query": "mutation templateDeploy($input: TemplateDeployV2Input!) { templateDeployV2(input: $input) { projectId workflowId } }",
        "variables": {
          "input": {
            "templateId": "56ef5ed9-bda6-49d1-a877-9476b8064d8c",
            "serializedConfig": {
              "buckets": {
                "c2036d4a-2a15-41ac-800a-e7955e900dd2": {
                  "name": "Galerie"
                }
              },
              "services": {
                "02a3865f-4237-49cc-a826-8c9ea1a036b6": {
                  "icon": "https://devicons.railway.app/i/postgresql.svg",
                  "name": "Postgres",
                  "deploy": {
                    "startCommand": null,
                    "healthcheckPath": null,
                    "restartPolicyType": "ON_FAILURE",
                    "restartPolicyMaxRetries": 10
                  },
                  "source": {
                    "image": "ghcr.io/railwayapp-templates/postgres-ssl:18"
                  },
                  "variables": {
                    "PGDATA": {
                      "isOptional": false,
                      "defaultValue": "{{PGDATA}}"
                    },
                    "PGHOST": {
                      "isOptional": false,
                      "defaultValue": "${{RAILWAY_PRIVATE_DOMAIN}}"
                    },
                    "PGPORT": {
                      "isOptional": false,
                      "defaultValue": "{{PGPORT}}"
                    },
                    "PGUSER": {
                      "isOptional": false,
                      "defaultValue": "${{POSTGRES_USER}}"
                    },
                    "PGDATABASE": {
                      "isOptional": false,
                      "defaultValue": "${{POSTGRES_DB}}"
                    },
                    "PGPASSWORD": {
                      "isOptional": false,
                      "defaultValue": "${{POSTGRES_PASSWORD}}"
                    },
                    "POSTGRES_DB": {
                      "isOptional": false,
                      "defaultValue": "{{POSTGRES_DB}}"
                    },
                    "DATABASE_URL": {
                      "isOptional": false,
                      "defaultValue": "postgresql://${{PGUSER}}:${{POSTGRES_PASSWORD}}@${{RAILWAY_PRIVATE_DOMAIN}}:5432/${{PGDATABASE}}"
                    },
                    "POSTGRES_USER": {
                      "isOptional": false,
                      "defaultValue": "{{POSTGRES_USER}}"
                    },
                    "SSL_CERT_DAYS": {
                      "isOptional": false,
                      "defaultValue": "{{SSL_CERT_DAYS}}"
                    },
                    "POSTGRES_PASSWORD": {
                      "isOptional": false,
                      "defaultValue": "{{POSTGRES_PASSWORD}}"
                    },
                    "RAILWAY_DEPLOYMENT_DRAINING_SECONDS": {
                      "isOptional": false,
                      "defaultValue": "{{RAILWAY_DEPLOYMENT_DRAINING_SECONDS}}"
                    }
                  },
                  "volumeMounts": {
                    "02a3865f-4237-49cc-a826-8c9ea1a036b6": {
                      "mountPath": "/var/lib/postgresql/data"
                    }
                  }
                },
                "38d5502d-5940-4738-aa01-e292ad0a7586": {
                  "icon": null,
                  "name": "carnet-de-combat",
                  "deploy": {
                    "startCommand": null,
                    "healthcheckPath": null,
                    "restartPolicyType": "ON_FAILURE",
                    "restartPolicyMaxRetries": 10
                  },
                  "source": {
                    "repo": "https://github.com/ismavld/carnet-de-combat",
                    "rootDirectory": null
                  },
                  "variables": {
                    "APP_URL": {
                      "isOptional": false,
                      "defaultValue": "{{APP_URL}}"
                    },
                    "DB_HOST": {
                      "isOptional": false,
                      "defaultValue": "${{Postgres.PGHOST}}"
                    },
                    "DB_NAME": {
                      "isOptional": false,
                      "defaultValue": "${{Postgres.PGDATABASE}}"
                    },
                    "DB_PORT": {
                      "isOptional": false,
                      "defaultValue": "${{Postgres.PGPORT}}"
                    },
                    "DB_USER": {
                      "isOptional": false,
                      "defaultValue": "${{Postgres.PGUSER}}"
                    },
                    "DB_PASSWORD": {
                      "isOptional": false,
                      "defaultValue": "${{Postgres.PGPASSWORD}}"
                    },
                    "MAIL_SECRET": {
                      "isOptional": false,
                      "defaultValue": "{{MAIL_SECRET}}"
                    },
                    "AWS_ENDPOINT_URL": {
                      "isOptional": false,
                      "defaultValue": "${{Galerie.ENDPOINT}}"
                    },
                    "AWS_ACCESS_KEY_ID": {
                      "isOptional": false,
                      "defaultValue": "${{Galerie.ACCESS_KEY_ID}}"
                    },
                    "MAIL_FUNCTION_URL": {
                      "isOptional": false,
                      "defaultValue": "http://${{function-bun.RAILWAY_PRIVATE_DOMAIN}}:8080"
                    },
                    "AWS_DEFAULT_REGION": {
                      "isOptional": false,
                      "defaultValue": "${{Galerie.REGION}}"
                    },
                    "AWS_S3_BUCKET_NAME": {
                      "isOptional": false,
                      "defaultValue": "${{Galerie.BUCKET}}"
                    },
                    "AWS_SECRET_ACCESS_KEY": {
                      "isOptional": false,
                      "defaultValue": "${{Galerie.SECRET_ACCESS_KEY}}"
                    }
                  },
                  "networking": {
                    "serviceDomains": {
                      "<hasDomain>:8080": {
                        "port": 8080
                      }
                    }
                  }
                },
                "dc282667-ad32-49b5-b916-998bb16aefc1": {
                  "icon": null,
                  "name": "function-bun",
                  "deploy": {
                    "startCommand": "./run.sh Ly8gaW5kZXgudHN4IChCdW4gcnVudGltZSkg4oCUIHNlcnZpY2UgImZ1bmN0aW9uLWJ1biIgc3VyIFJhaWx3YXkuCi8vIENvcGllIGRlIHLDqWbDqXJlbmNlIGR1IGNvZGUgY29sbMOpIGRhbnMgbCdvbmdsZXQgIlNvdXJjZSBDb2RlIiBkZSBsYSBmdW5jdGlvbiA6Ci8vIHRvdXRlIG1vZGlmaWNhdGlvbiBpY2kgZG9pdCDDqnRyZSByZWNvcGnDqWUgbMOgLWJhcyAoY2UgZmljaGllciBuJ2VzdCBwYXMgZMOpcGxvecOpKS4KLy8KLy8gUsO0bGUgOiByZWNldm9pciB1bmUgZGVtYW5kZSBkJ2Vudm9pIGRlcHVpcyBsJ2FwcCBQSFAgKGF1dGhlbnRpZmnDqWUgcGFyIHVuIHNlY3JldAovLyBwYXJ0YWfDqSkgZXQgbCdlbnZveWVyIHZpYSBsJ0FQSSBSZXNlbmQgYXZlYyBsZSBib24gdGVtcGxhdGUuIExhIGZ1bmN0aW9uIG5lCi8vIGNvbm5hw650IG5pIGxhIGJhc2UgbmkgbGVzIGpldG9ucyA6IGVsbGUgc2UgY29udGVudGUgZCdlbnZveWVyLgovLwovLyBHYXJkZS1mb3VzIGFudGkgInJlbGFpcyBvdXZlcnQiIDogc2V1bHMgNCB0eXBlcyBzb250IGFjY2VwdMOpcywgbCdleHDDqWRpdGV1ciBlc3QKLy8gZml4w6kgaWNpIHBhciB0eXBlIChqYW1haXMgZm91cm5pIHBhciBsJ2FwcGVsYW50KSwgZXQgbGVzIHZhcmlhYmxlcyBhdHRlbmR1ZXMKLy8gc29udCBsaXN0w6llcyBwYXIgdHlwZSAobGVzIGF1dHJlcyBzb250IGlnbm9yw6llcykuCi8vCi8vIFZhcmlhYmxlcyBSYWlsd2F5IG7DqWNlc3NhaXJlcyA6Ci8vICAgUkVTRU5EX0FQSV9LRVksIE1BSUxfU0VDUkVULAovLyAgIFRFTVBMQVRFX1ZBTElEQVRFX0lELCBURU1QTEFURV9SRVNFVF9JRCwKLy8gICBURU1QTEFURV9DSEFOR0VNQUlMX0lELCBURU1QTEFURV9DSEFOR0VNQUlMX0FMRVJUX0lECmltcG9ydCB7IEhvbm8gfSBmcm9tICJob25vQDQiOwoKdHlwZSBNYWlsVHlwZSA9ICJ2YWxpZGF0ZSIgfCAicmVzZXQiIHwgImNoYW5nZW1haWwiIHwgImNoYW5nZW1haWwtYWxlcnQiOwoKY29uc3QgTUFJTFM6IFJlY29yZDxNYWlsVHlwZSwgeyBmcm9tOiBzdHJpbmc7IHN1YmplY3Q6IHN0cmluZzsgdGVtcGxhdGU6IHN0cmluZzsgdmFyczogc3RyaW5nW10gfT4gPSB7CiAgdmFsaWRhdGU6IHsKICAgIGZyb206ICJDYXJuZXQgZGUgQ29tYmF0IDxjYy12YWxpZGF0ZUBpc21hZWwtdmlsbGFsZGVhLmZyPiIsCiAgICBzdWJqZWN0OiAiQ29uZmlybWUgdG9uIGNvbXB0ZSBDYXJuZXQgZGUgQ29tYmF0IiwKICAgIHRlbXBsYXRlOiAiVEVNUExBVEVfVkFMSURBVEVfSUQiLAogICAgdmFyczogWyJQU0VVRE8iLCAiQ09ORklSTV9VUkwiXSwKICB9LAogIHJlc2V0OiB7CiAgICBmcm9tOiAiQ2FybmV0IGRlIENvbWJhdCA8Y2MtcmVzZXRAaXNtYWVsLXZpbGxhbGRlYS5mcj4iLAogICAgc3ViamVjdDogIkNoYW5nZSB0b24gbW90IGRlIHBhc3NlIiwKICAgIHRlbXBsYXRlOiAiVEVNUExBVEVfUkVTRVRfSUQiLAogICAgdmFyczogWyJQU0VVRE8iLCAiUkVTRVRfVVJMIl0sCiAgfSwKICBjaGFuZ2VtYWlsOiB7CiAgICBmcm9tOiAiQ2FybmV0IGRlIENvbWJhdCA8Y2MtY2hhbmdlbWFpbEBpc21hZWwtdmlsbGFsZGVhLmZyPiIsCiAgICBzdWJqZWN0OiAiQ29uZmlybWUgdGEgbm91dmVsbGUgYWRyZXNzZSBlbWFpbCIsCiAgICB0ZW1wbGF0ZTogIlRFTVBMQVRFX0NIQU5HRU1BSUxfSUQiLAogICAgdmFyczogWyJQU0VVRE8iLCAiTkVXX0VNQUlMIiwgIkNPTkZJUk1fVVJMIl0sCiAgfSwKICAiY2hhbmdlbWFpbC1hbGVydCI6IHsKICAgIGZyb206ICJDYXJuZXQgZGUgQ29tYmF0IDxjYy1jaGFuZ2VtYWlsQGlzbWFlbC12aWxsYWxkZWEuZnI+IiwKICAgIHN1YmplY3Q6ICJUb24gYWRyZXNzZSBlbWFpbCBhIMOpdMOpIGNoYW5nw6llIiwKICAgIHRlbXBsYXRlOiAiVEVNUExBVEVfQ0hBTkdFTUFJTF9BTEVSVF9JRCIsCiAgICB2YXJzOiBbIlBTRVVETyIsICJORVdfRU1BSUxfTUFTS0VEIl0sCiAgfSwKfTsKCmNvbnN0IGVudiA9IChrOiBzdHJpbmcpID0+IChpbXBvcnQubWV0YS5lbnZba10gPz8gIiIpLnRyaW0oKTsKCi8vIENvbXBhcmFpc29uIGVuIHRlbXBzIGNvbnN0YW50IGR1IHNlY3JldCAow6l2aXRlIGRlIGxlIGRldmluZXIgb2N0ZXQgcGFyIG9jdGV0KS4KZnVuY3Rpb24gc2FmZUVxdWFsKGE6IHN0cmluZywgYjogc3RyaW5nKTogYm9vbGVhbiB7CiAgY29uc3QgeCA9IG5ldyBUZXh0RW5jb2RlcigpLmVuY29kZShhKTsKICBjb25zdCB5ID0gbmV3IFRleHRFbmNvZGVyKCkuZW5jb2RlKGIpOwogIGlmICh4Lmxlbmd0aCAhPT0geS5sZW5ndGggfHwgeC5sZW5ndGggPT09IDApIHJldHVybiBmYWxzZTsKICBsZXQgZGlmZiA9IDA7CiAgZm9yIChsZXQgaSA9IDA7IGkgPCB4Lmxlbmd0aDsgaSsrKSBkaWZmIHw9IHhbaV0gXiB5W2ldOwogIHJldHVybiBkaWZmID09PSAwOwp9Cgpjb25zdCBpc0VtYWlsID0gKHM6IHVua25vd24pOiBzIGlzIHN0cmluZyA9PgogIHR5cGVvZiBzID09PSAic3RyaW5nIiAmJiBzLmxlbmd0aCA8PSAyNTQgJiYgL15bXlxzQDw+LDsiXStAW15cc0A8Piw7Il0rXC5bXlxzQDw+LDsiXSskLy50ZXN0KHMpOwoKY29uc3QgYXBwID0gbmV3IEhvbm8oKTsKCmFwcC5nZXQoIi9hcGkvaGVhbHRoIiwgKGMpID0+IGMuanNvbih7IHN0YXR1czogIm9rIiB9KSk7CgphcHAucG9zdCgiL3NlbmQiLCBhc3luYyAoYykgPT4gewogIGNvbnN0IHNlY3JldCA9IGVudigiTUFJTF9TRUNSRVQiKTsKICBjb25zdCBhdXRoID0gYy5yZXEuaGVhZGVyKCJhdXRob3JpemF0aW9uIikgPz8gIiI7CiAgaWYgKCFzZWNyZXQgfHwgIXNhZmVFcXVhbChhdXRoLCBgQmVhcmVyICR7c2VjcmV0fWApKSB7CiAgICByZXR1cm4gYy5qc29uKHsgZXJyb3I6ICJ1bmF1dGhvcml6ZWQiIH0sIDQwMSk7CiAgfQoKICBsZXQgYm9keTogYW55OwogIHRyeSB7CiAgICBib2R5ID0gYXdhaXQgYy5yZXEuanNvbigpOwogIH0gY2F0Y2ggewogICAgcmV0dXJuIGMuanNvbih7IGVycm9yOiAiaW52YWxpZF9qc29uIiB9LCA0MDApOwogIH0KCiAgY29uc3QgdHlwZSA9IGJvZHk/LnR5cGUgYXMgTWFpbFR5cGU7CiAgY29uc3QgbWFpbCA9IE1BSUxTW3R5cGVdOwogIGlmICghbWFpbCkgcmV0dXJuIGMuanNvbih7IGVycm9yOiAidW5rbm93bl90eXBlIiB9LCA0MDApOwogIGlmICghaXNFbWFpbChib2R5Py50bykpIHJldHVybiBjLmpzb24oeyBlcnJvcjogImludmFsaWRfdG8iIH0sIDQwMCk7CgogIGNvbnN0IHRlbXBsYXRlSWQgPSBlbnYobWFpbC50ZW1wbGF0ZSk7CiAgY29uc3QgYXBpS2V5ID0gZW52KCJSRVNFTkRfQVBJX0tFWSIpOwogIGlmICghdGVtcGxhdGVJZCB8fCAhYXBpS2V5KSByZXR1cm4gYy5qc29uKHsgZXJyb3I6ICJub3RfY29uZmlndXJlZCIsIG1pc3Npbmc6ICFhcGlLZXkgPyAiUkVTRU5EX0FQSV9LRVkiIDogbWFpbC50ZW1wbGF0ZSB9LCA1MDApOwoKICBjb25zdCB2YXJpYWJsZXM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTsKICBmb3IgKGNvbnN0IGsgb2YgbWFpbC52YXJzKSB7CiAgICBjb25zdCB2ID0gYm9keT8udmFyaWFibGVzPy5ba107CiAgICBpZiAodHlwZW9mIHYgIT09ICJzdHJpbmciIHx8IHYgPT09ICIiIHx8IHYubGVuZ3RoID4gMjAwMCkgewogICAgICByZXR1cm4gYy5qc29uKHsgZXJyb3I6ICJpbnZhbGlkX3ZhcmlhYmxlIiwgdmFyaWFibGU6IGsgfSwgNDAwKTsKICAgIH0KICAgIHZhcmlhYmxlc1trXSA9IHY7CiAgfQoKICBjb25zdCByZXMgPSBhd2FpdCBmZXRjaCgiaHR0cHM6Ly9hcGkucmVzZW5kLmNvbS9lbWFpbHMiLCB7CiAgICBtZXRob2Q6ICJQT1NUIiwKICAgIGhlYWRlcnM6IHsgQXV0aG9yaXphdGlvbjogYEJlYXJlciAke2FwaUtleX1gLCAiQ29udGVudC1UeXBlIjogImFwcGxpY2F0aW9uL2pzb24iIH0sCiAgICBib2R5OiBKU09OLnN0cmluZ2lmeSh7CiAgICAgIGZyb206IG1haWwuZnJvbSwKICAgICAgdG86IFtib2R5LnRvXSwKICAgICAgc3ViamVjdDogbWFpbC5zdWJqZWN0LAogICAgICB0ZW1wbGF0ZTogeyBpZDogdGVtcGxhdGVJZCwgdmFyaWFibGVzIH0sCiAgICB9KSwKICB9KTsKICBjb25zdCBvdXQgPSBhd2FpdCByZXMuanNvbigpLmNhdGNoKCgpID0+ICh7fSkpOwogIGlmICghcmVzLm9rKSB7CiAgICBjb25zb2xlLmVycm9yKCJSZXNlbmQgZXJyb3IiLCByZXMuc3RhdHVzLCBKU09OLnN0cmluZ2lmeShvdXQpKTsKICAgIHJldHVybiBjLmpzb24oeyBlcnJvcjogInJlc2VuZF9mYWlsZWQiLCBzdGF0dXM6IHJlcy5zdGF0dXMgfSwgNTAyKTsKICB9CiAgY29uc29sZS5sb2coYHNlbnQgJHt0eXBlfSBpZD0ke291dD8uaWR9YCk7CiAgcmV0dXJuIGMuanNvbih7IG9rOiB0cnVlLCBpZDogb3V0Py5pZCA/PyBudWxsIH0pOwp9KTsKCkJ1bi5zZXJ2ZSh7CiAgLy8gIjo6IiA9IMOpY291dGUgZW4gSVB2NCBFVCBJUHY2IDogbsOpY2Vzc2FpcmUgcG91ciBsZSByw6lzZWF1IHByaXbDqSBSYWlsd2F5CiAgLy8gKGZ1bmN0aW9uLWJ1bi5yYWlsd2F5LmludGVybmFsIG5lIHLDqXBvbmQgcXUnZW4gSVB2NikuCiAgaG9zdG5hbWU6ICI6OiIsCiAgcG9ydDogTnVtYmVyKGltcG9ydC5tZXRhLmVudi5QT1JUID8/IDMwMDApLAogIGZldGNoOiBhcHAuZmV0Y2gsCn0pOwo=",
                    "healthcheckPath": null,
                    "restartPolicyType": "ON_FAILURE",
                    "restartPolicyMaxRetries": 10
                  },
                  "source": {
                    "image": "ghcr.io/railwayapp/function-bun:1.4.4"
                  },
                  "variables": {
                    "MAIL_SECRET": {
                      "isOptional": false,
                      "defaultValue": "{{MAIL_SECRET}}"
                    },
                    "RESEND_API_KEY": {
                      "isOptional": false,
                      "defaultValue": "{{RESEND_API_KEY}}"
                    },
                    "TEMPLATE_RESET_ID": {
                      "isOptional": false,
                      "defaultValue": "{{TEMPLATE_RESET_ID}}"
                    },
                    "TEMPLATE_VALIDATE_ID": {
                      "isOptional": false,
                      "defaultValue": "{{TEMPLATE_VALIDATE_ID}}"
                    },
                    "TEMPLATE_CHANGEMAIL_ID": {
                      "isOptional": false,
                      "defaultValue": "{{TEMPLATE_CHANGEMAIL_ID}}"
                    },
                    "TEMPLATE_CHANGEMAIL_ALERT_ID": {
                      "isOptional": false,
                      "defaultValue": "{{TEMPLATE_CHANGEMAIL_ALERT_ID}}"
                    }
                  },
                  "networking": {
                    "serviceDomains": {
                      "<hasDomain>:8080": {
                        "port": 8080
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "post_deploy": {},
  "resources": {
    "expected_services": 3,
    "needs_volume": true
  },
  "generated_at": "2026-11-06T16:15:12.187Z",
  "generator_version": "0.1.0"
}
