{"id":21401018,"url":"https://github.com/massdriver-cloud/airlock","last_synced_at":"2025-07-13T21:31:38.614Z","repository":{"id":209261430,"uuid":"634775608","full_name":"massdriver-cloud/airlock","owner":"massdriver-cloud","description":"Generate JSON Schema from various sources (terraform, helm)","archived":false,"fork":false,"pushed_at":"2024-11-18T18:33:15.000Z","size":411,"stargazers_count":4,"open_issues_count":1,"forks_count":2,"subscribers_count":3,"default_branch":"main","last_synced_at":"2024-11-18T19:40:41.882Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://massdriver.cloud","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/massdriver-cloud.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-05-01T06:43:49.000Z","updated_at":"2024-10-21T17:26:47.000Z","dependencies_parsed_at":"2024-07-28T02:43:39.212Z","dependency_job_id":"02497c91-b6c3-4abc-a671-74272b4d0c3c","html_url":"https://github.com/massdriver-cloud/airlock","commit_stats":null,"previous_names":["massdriver-cloud/airlock"],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/massdriver-cloud%2Fairlock","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/massdriver-cloud%2Fairlock/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/massdriver-cloud%2Fairlock/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/massdriver-cloud%2Fairlock/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/massdriver-cloud","download_url":"https://codeload.github.com/massdriver-cloud/airlock/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225918921,"owners_count":17545151,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-22T15:25:44.129Z","updated_at":"2024-11-22T15:25:44.844Z","avatar_url":"https://github.com/massdriver-cloud.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cimg src=\"images/logo.png\" width=\"400\" height=\"400\"\u003e\n\n# AIRLOCK\n\n[![Go Report Card](https://goreportcard.com/badge/github.com/massdriver-cloud/airlock)](https://goreportcard.com/report/github.com/massdriver-cloud/airlock)\n[![License](https://img.shields.io/github/license/massdriver-cloud/airlock)](https://github.com/massdriver-cloud/airlock/blob/master/LICENSE)\n\n## Overview\n\nTranslate between JSON Schema and common IaC languages (opentofu, helm, bicep)\n\n## Getting Started\n\n### Prerequisites\n\n- Go version 1.22\n\n### Installation\n\nTo install this package, simply run:\n\n```bash\ngo get -u github.com/massdriver-cloud/airlock\n```\n\n### Usage\n\n#### OpenTofu\n\nOpenTofu -\u003e JSON Schema:\n\n```bash\nairlock opentofu input /path/to/module\n```\n\n\u003cdetails\u003e\n    \u003csummary\u003eExample\u003c/summary\u003e\n\n`main.tf`:\n\n```terraform\nprovider \"aws\" {\n  region = var.region\n}\n\nvariable \"bucket_name\" {\n  description = \"The name of the S3 bucket.\"\n  type        = string\n}\n\nvariable \"region\" {\n  description = \"The AWS region to create the S3 bucket in.\"\n  type        = string\n  default     = \"us-east-1\"\n}\n\nvariable \"enable_versioning\" {\n  description = \"Enable versioning on the S3 bucket.\"\n  type        = bool\n  default     = false\n}\n\nvariable \"acl\" {\n  description = \"The access control list for the S3 bucket.\"\n  type        = string\n  default     = \"private\"\n}\n\nresource \"aws_s3_bucket\" \"example\" {\n  bucket = var.bucket_name\n  acl    = var.acl\n\n  versioning {\n    enabled = var.enable_versioning\n  }\n\n  lifecycle_rule {\n    id      = \"delete-old-versions\"\n    enabled = true\n\n    noncurrent_version_expiration {\n      days = 30\n    }\n  }\n\n  tags = {\n    Name        = var.bucket_name\n    Environment = \"Dev\"\n  }\n}\n\noutput \"bucket_id\" {\n  value = aws_s3_bucket.example.id\n}\n\noutput \"bucket_arn\" {\n  value = aws_s3_bucket.example.arn\n}\n```\n\nJSON output:\n\n```json\n{\n  \"properties\": {\n    \"bucket_name\": {\n      \"type\": \"string\",\n      \"title\": \"bucket_name\",\n      \"description\": \"The name of the S3 bucket.\"\n    },\n    \"region\": {\n      \"type\": \"string\",\n      \"title\": \"region\",\n      \"description\": \"The AWS region to create the S3 bucket in.\",\n      \"default\": \"us-east-1\"\n    },\n    \"enable_versioning\": {\n      \"type\": \"boolean\",\n      \"title\": \"enable_versioning\",\n      \"description\": \"Enable versioning on the S3 bucket.\",\n      \"default\": false\n    },\n    \"acl\": {\n      \"type\": \"string\",\n      \"title\": \"acl\",\n      \"description\": \"The access control list for the S3 bucket.\",\n      \"default\": \"private\"\n    }\n  },\n  \"required\": [\n    \"acl\",\n    \"bucket_name\",\n    \"enable_versioning\",\n    \"region\"\n  ]\n}\n```\n\n\u003c/details\u003e\n\nJSON Schema -\u003e OpenTofu:\n\n```bash\nairlock opentofu output /path/to/schema.json\n```\n\n\u003cdetails\u003e\n    \u003csummary\u003eExample\u003c/summary\u003e\n\n`schema.json`:\n\n```json\n{\n  \"properties\": {\n    \"form\": {\n      \"title\": \"Form\",\n      \"type\": \"object\",\n      \"required\": [\n        \"firstName\",\n        \"lastName\"\n      ],\n      \"properties\": {\n        \"firstName\": {\n          \"type\": \"string\",\n          \"title\": \"First name\"\n        },\n        \"lastName\": {\n          \"type\": \"string\",\n          \"title\": \"Last name\"\n        },\n        \"age\": {\n          \"type\": \"integer\",\n          \"title\": \"Age\"\n        },\n        \"bio\": {\n          \"type\": \"string\",\n          \"title\": \"Bio\"\n        },\n        \"password\": {\n          \"type\": \"string\",\n          \"title\": \"Password\",\n          \"minLength\": 3\n        },\n        \"telephone\": {\n          \"type\": \"string\",\n          \"title\": \"Telephone\",\n          \"minLength\": 10\n        }\n      }\n    }\n  }\n}\n```\n\nOpenTofu output:\n\n```terraform\nvariable \"form\" {\n  type = object({\n    firstName = string\n    lastName  = string\n    age       = optional(number)\n    bio       = optional(string)\n    password  = optional(string)\n    telephone = optional(string)\n  })\n  default = null\n}\n```\n\n\u003c/details\u003e\n\n#### Helm\n\nHelm -\u003e JSON Schema:\n\n```bash\nairlock helm input /path/to/values.yaml\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003eExample\u003c/summary\u003e\n\n`values.yaml`:\n\n```yaml\nname: my-app\n\nimage:\n  repository: my-app-repo/my-app\n  tag: latest\n  pullPolicy: IfNotPresent\n\nservice:\n  enabled: true\n  type: ClusterIP\n  port: 80\n  targetPort: 8080\n\ningress:\n  enabled: false\n  path: /\n  hosts:\n    - host: my-app.local\n      paths:\n        - /\n  tls: []\n\nreplicaCount: 1\n\nresources:\n  requests:\n    cpu: \"100m\"\n    memory: \"256Mi\"\n  limits:\n    cpu: \"500m\"\n    memory: \"512Mi\"\n\nenv:\n  - name: DATABASE_URL\n    value: postgres://user:password@postgres:5432/mydb\n  - name: APP_SECRET\n    value: supersecretkey\n\nlogging:\n  level: info\n\npersistence:\n  enabled: false\n  storageClass: \"standard\"\n  accessModes:\n    - ReadWriteOnce\n  size: 1Gi\n\nannotations: {}\n\nnodeSelector: {}\n\ntolerations: []\n\naffinity: {}\n```\n\nJSON Schema output:\n\n```json\n{\n  \"properties\": {\n    \"name\": {\n      \"type\": \"string\",\n      \"title\": \"name\",\n      \"description\": \"Application name\",\n      \"default\": \"my-app\"\n    },\n    \"image\": {\n      \"properties\": {\n        \"repository\": {\n          \"type\": \"string\",\n          \"title\": \"repository\",\n          \"default\": \"my-app-repo/my-app\"\n        },\n        \"tag\": {\n          \"type\": \"string\",\n          \"title\": \"tag\",\n          \"default\": \"latest\"\n        },\n        \"pullPolicy\": {\n          \"type\": \"string\",\n          \"title\": \"pullPolicy\",\n          \"default\": \"IfNotPresent\"\n        }\n      },\n      \"type\": \"object\",\n      \"required\": [\n        \"repository\",\n        \"tag\",\n        \"pullPolicy\"\n      ],\n      \"title\": \"image\",\n      \"description\": \"Image configuration\"\n    },\n    \"service\": {\n      \"properties\": {\n        \"enabled\": {\n          \"type\": \"boolean\",\n          \"title\": \"enabled\",\n          \"default\": true\n        },\n        \"type\": {\n          \"type\": \"string\",\n          \"title\": \"type\",\n          \"default\": \"ClusterIP\"\n        },\n        \"port\": {\n          \"type\": \"integer\",\n          \"title\": \"port\",\n          \"default\": 80\n        },\n        \"targetPort\": {\n          \"type\": \"integer\",\n          \"title\": \"targetPort\",\n          \"default\": 8080\n        }\n      },\n      \"type\": \"object\",\n      \"required\": [\n        \"enabled\",\n        \"type\",\n        \"port\",\n        \"targetPort\"\n      ],\n      \"title\": \"service\",\n      \"description\": \"Service configuration\"\n    },\n    \"ingress\": {\n      \"properties\": {\n        \"enabled\": {\n          \"type\": \"boolean\",\n          \"title\": \"enabled\",\n          \"default\": false\n        },\n        \"path\": {\n          \"type\": \"string\",\n          \"title\": \"path\",\n          \"default\": \"/\"\n        },\n        \"hosts\": {\n          \"items\": {\n            \"properties\": {\n              \"host\": {\n                \"type\": \"string\",\n                \"title\": \"host\",\n                \"default\": \"my-app.local\"\n              },\n              \"paths\": {\n                \"items\": {\n                  \"type\": \"string\",\n                  \"default\": \"/\"\n                },\n                \"type\": \"array\",\n                \"title\": \"paths\",\n                \"default\": [\n                  \"/\"\n                ]\n              }\n            },\n            \"type\": \"object\",\n            \"required\": [\n              \"host\",\n              \"paths\"\n            ]\n          },\n          \"type\": \"array\",\n          \"title\": \"hosts\",\n          \"default\": [\n            {\n              \"host\": \"my-app.local\",\n              \"paths\": [\n                \"/\"\n              ]\n            }\n          ]\n        },\n        \"tls\": {\n          \"items\": {\n            \"properties\": {\n              \"secretName\": {\n                \"type\": \"string\",\n                \"title\": \"secretName\",\n                \"default\": \"my-app-tls\"\n              },\n              \"hosts\": {\n                \"items\": {\n                  \"type\": \"string\",\n                  \"default\": \"my-app.local\"\n                },\n                \"type\": \"array\",\n                \"title\": \"hosts\",\n                \"default\": [\n                  \"my-app.local\"\n                ]\n              }\n            },\n            \"type\": \"object\",\n            \"required\": [\n              \"secretName\",\n              \"hosts\"\n            ]\n          },\n          \"type\": \"array\",\n          \"title\": \"tls\",\n          \"default\": [\n            {\n              \"hosts\": [\n                \"my-app.local\"\n              ],\n              \"secretName\": \"my-app-tls\"\n            }\n          ]\n        }\n      },\n      \"type\": \"object\",\n      \"required\": [\n        \"enabled\",\n        \"path\",\n        \"hosts\",\n        \"tls\"\n      ],\n      \"title\": \"ingress\",\n      \"description\": \"Ingress configuration\"\n    },\n    \"replicaCount\": {\n      \"type\": \"integer\",\n      \"title\": \"replicaCount\",\n      \"description\": \"Replicas configuration\",\n      \"default\": 1\n    },\n    \"resources\": {\n      \"properties\": {\n        \"requests\": {\n          \"properties\": {\n            \"cpu\": {\n              \"type\": \"string\",\n              \"title\": \"cpu\",\n              \"default\": \"100m\"\n            },\n            \"memory\": {\n              \"type\": \"string\",\n              \"title\": \"memory\",\n              \"default\": \"256Mi\"\n            }\n          },\n          \"type\": \"object\",\n          \"required\": [\n            \"cpu\",\n            \"memory\"\n          ],\n          \"title\": \"requests\"\n        },\n        \"limits\": {\n          \"properties\": {\n            \"cpu\": {\n              \"type\": \"string\",\n              \"title\": \"cpu\",\n              \"default\": \"500m\"\n            },\n            \"memory\": {\n              \"type\": \"string\",\n              \"title\": \"memory\",\n              \"default\": \"512Mi\"\n            }\n          },\n          \"type\": \"object\",\n          \"required\": [\n            \"cpu\",\n            \"memory\"\n          ],\n          \"title\": \"limits\"\n        }\n      },\n      \"type\": \"object\",\n      \"required\": [\n        \"requests\",\n        \"limits\"\n      ],\n      \"title\": \"resources\",\n      \"description\": \"Resource requests and limits\"\n    },\n    \"env\": {\n      \"items\": {\n        \"properties\": {\n          \"name\": {\n            \"type\": \"string\",\n            \"title\": \"name\",\n            \"default\": \"DATABASE_URL\"\n          },\n          \"value\": {\n            \"type\": \"string\",\n            \"title\": \"value\",\n            \"default\": \"postgres://user:password@postgres:5432/mydb\"\n          }\n        },\n        \"type\": \"object\",\n        \"required\": [\n          \"name\",\n          \"value\"\n        ]\n      },\n      \"type\": \"array\",\n      \"title\": \"env\",\n      \"description\": \"Environment variables\",\n      \"default\": [\n        {\n          \"name\": \"DATABASE_URL\",\n          \"value\": \"postgres://user:password@postgres:5432/mydb\"\n        },\n        {\n          \"name\": \"APP_SECRET\",\n          \"value\": \"supersecretkey\"\n        }\n      ]\n    },\n    \"logging\": {\n      \"properties\": {\n        \"level\": {\n          \"type\": \"string\",\n          \"title\": \"level\",\n          \"default\": \"info\"\n        }\n      },\n      \"type\": \"object\",\n      \"required\": [\n        \"level\"\n      ],\n      \"title\": \"logging\",\n      \"description\": \"Logging configuration\"\n    },\n    \"persistence\": {\n      \"properties\": {\n        \"enabled\": {\n          \"type\": \"boolean\",\n          \"title\": \"enabled\",\n          \"default\": false\n        },\n        \"storageClass\": {\n          \"type\": \"string\",\n          \"title\": \"storageClass\",\n          \"default\": \"standard\"\n        },\n        \"accessModes\": {\n          \"items\": {\n            \"type\": \"string\",\n            \"default\": \"ReadWriteOnce\"\n          },\n          \"type\": \"array\",\n          \"title\": \"accessModes\",\n          \"default\": [\n            \"ReadWriteOnce\"\n          ]\n        },\n        \"size\": {\n          \"type\": \"string\",\n          \"title\": \"size\",\n          \"default\": \"1Gi\"\n        }\n      },\n      \"type\": \"object\",\n      \"required\": [\n        \"enabled\",\n        \"storageClass\",\n        \"accessModes\",\n        \"size\"\n      ],\n      \"title\": \"persistence\",\n      \"description\": \"Persistent storage configuration\"\n    },\n    \"annotations\": {\n      \"properties\": {},\n      \"type\": \"object\",\n      \"title\": \"annotations\",\n      \"description\": \"Custom annotations\"\n    },\n    \"nodeSelector\": {\n      \"properties\": {},\n      \"type\": \"object\",\n      \"title\": \"nodeSelector\",\n      \"description\": \"Node selector\"\n    },\n    \"tolerations\": {\n      \"items\": {\n        \"properties\": {\n          \"key\": {\n            \"type\": \"string\",\n            \"title\": \"key\",\n            \"default\": \"key1\"\n          },\n          \"operator\": {\n            \"type\": \"string\",\n            \"title\": \"operator\",\n            \"default\": \"Equal\"\n          },\n          \"value\": {\n            \"type\": \"string\",\n            \"title\": \"value\",\n            \"default\": \"value1\"\n          },\n          \"effect\": {\n            \"type\": \"string\",\n            \"title\": \"effect\",\n            \"default\": \"NoSchedule\"\n          }\n        },\n        \"type\": \"object\",\n        \"required\": [\n          \"key\",\n          \"operator\",\n          \"value\",\n          \"effect\"\n        ]\n      },\n      \"type\": \"array\",\n      \"title\": \"tolerations\",\n      \"description\": \"Tolerations\",\n      \"default\": [\n        {\n          \"effect\": \"NoSchedule\",\n          \"key\": \"key1\",\n          \"operator\": \"Equal\",\n          \"value\": \"value1\"\n        },\n        {\n          \"effect\": \"NoExecute\",\n          \"key\": \"key2\",\n          \"operator\": \"Exists\"\n        }\n      ]\n    },\n    \"affinity\": {\n      \"properties\": {},\n      \"type\": \"object\",\n      \"title\": \"affinity\",\n      \"description\": \"Affinity settings\"\n    }\n  },\n  \"type\": \"object\",\n  \"required\": [\n    \"name\",\n    \"image\",\n    \"service\",\n    \"ingress\",\n    \"replicaCount\",\n    \"resources\",\n    \"env\",\n    \"logging\",\n    \"persistence\",\n    \"annotations\",\n    \"nodeSelector\",\n    \"tolerations\",\n    \"affinity\"\n  ]\n}\n```\n\n\u003c/details\u003e\n\n#### Bicep\n\nBicep -\u003e JSON Schema:\n\n```bash\nairlock bicep input /path/to/template.bicep\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003eExample\u003c/summary\u003e\n\n`template.bicep`:\n\n```bicep\n@description('The name of the resource group.')\nparam resourceGroupName string\n\n@description('The location where the storage account will be deployed.')\nparam location string = resourceGroup().location\n\n@description('The name of the storage account.')\n@secure()\nparam storageAccountName string\n\n@description('The SKU for the storage account.')\n@allowed([\n  'Standard_LRS'\n  'Standard_GRS'\n  'Standard_RAGRS'\n  'Standard_ZRS'\n  'Premium_LRS'\n])\nparam sku string = 'Standard_LRS'\n\n@description('The kind of storage account.')\n@allowed([\n  'StorageV2'\n  'Storage'\n  'BlobStorage'\n  'FileStorage'\n  'BlockBlobStorage'\n])\nparam kind string = 'StorageV2'\n\nresource storageAccount 'Microsoft.Storage/storageAccounts@2021-09-01' = {\n  name: storageAccountName\n  location: location\n  sku: {\n    name: sku\n  }\n  kind: kind\n  properties: {\n    supportsHttpsTrafficOnly: true\n  }\n}\n\noutput storageAccountId string = storageAccount.id\noutput storageAccountPrimaryEndpoints object = storageAccount.properties.primaryEndpoints\n```\n\nJSON Schema output:\n\n```json\n{\n  \"properties\": {\n    \"storageAccountName\": {\n      \"type\": \"string\",\n      \"format\": \"password\",\n      \"title\": \"storageAccountName\",\n      \"description\": \"The name of the storage account.\"\n    },\n    \"kind\": {\n      \"type\": \"string\",\n      \"enum\": [\n        \"StorageV2\",\n        \"Storage\",\n        \"BlobStorage\",\n        \"FileStorage\",\n        \"BlockBlobStorage\"\n      ],\n      \"title\": \"kind\",\n      \"description\": \"The kind of storage account.\",\n      \"default\": \"StorageV2\"\n    },\n    \"location\": {\n      \"type\": \"string\",\n      \"title\": \"location\",\n      \"description\": \"The location where the storage account will be deployed.\",\n      \"default\": \"[resourceGroup().location]\"\n    },\n    \"resourceGroupName\": {\n      \"type\": \"string\",\n      \"title\": \"resourceGroupName\",\n      \"description\": \"The name of the resource group.\"\n    },\n    \"sku\": {\n      \"type\": \"string\",\n      \"enum\": [\n        \"Standard_LRS\",\n        \"Standard_GRS\",\n        \"Standard_RAGRS\",\n        \"Standard_ZRS\",\n        \"Premium_LRS\"\n      ],\n      \"title\": \"sku\",\n      \"description\": \"The SKU for the storage account.\",\n      \"default\": \"Standard_LRS\"\n    }\n  },\n  \"type\": \"object\",\n  \"required\": [\n    \"kind\",\n    \"location\",\n    \"resourceGroupName\",\n    \"sku\",\n    \"storageAccountName\"\n  ]\n}\n```\n\n\u003c/details\u003e\n\nJSON Schema -\u003e Bicep:\n\n```bash\nairlock bicep output /path/to/schema.json\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003eExample\u003c/summary\u003e\n\n`schema.json`:\n\n```json\n{\n  \"properties\": {\n    \"firstName\": {\n      \"title\": \"First name\",\n      \"type\": \"string\"\n    },\n    \"lastName\": {\n      \"title\": \"Last name\",\n      \"type\": \"string\"\n    },\n    \"phoneNumber\": {\n      \"title\": \"Phone number\",\n      \"type\": \"string\",\n      \"minLength\": 9,\n      \"maxLength\": 12\n    },\n    \"email\": {\n      \"title\": \"Email\",\n      \"type\": \"string\",\n      \"minLength\": 3\n    },\n    \"age\": {\n      \"title\": \"Age\",\n      \"type\": \"integer\",\n      \"minimum\": 1\n    },\n    \"ssn\": {\n      \"title\": \"SSN\",\n      \"type\": \"string\",\n      \"format\": \"password\",\n      \"minLength\": 9,\n      \"maxLength\": 9\n    },\n    \"color\": {\n      \"title\": \"Favorite color\",\n      \"type\": \"string\",\n      \"enum\": [\n        \"Blue\",\n        \"Red\",\n        \"Yellow\",\n        \"Other\"\n      ]\n    },\n    \"active\": {\n      \"title\": \"User is active\",\n      \"description\": \"Is the user currently active?\",\n      \"type\": \"boolean\",\n      \"default\": false\n    }\n  }\n}\n```\n\nBicep output:\n\n```bicep\nparam firstName string\nparam lastName string\n@minLength(9)\n@maxLength(12)\nparam phoneNumber string\n@minLength(3)\nparam email string\n@minValue(1)\nparam age int\n@minLength(9)\n@maxLength(9)\n@secure()\nparam ssn string\n@allowed([\n  'Blue'\n  'Red'\n  'Yellow'\n  'Other'\n])\nparam color string\n@sys.description('Is the user currently active?')\nparam active bool = false\n```\n\n\u003c/details\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmassdriver-cloud%2Fairlock","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmassdriver-cloud%2Fairlock","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmassdriver-cloud%2Fairlock/lists"}