|
1 | 1 | # devcloud |
2 | 2 |
|
3 | | -Local cloud service emulator focused first on a MailHog-like SMTP inbox. |
| 3 | +Local cloud service emulator for development and E2E inspection. |
4 | 4 |
|
5 | | -## Mail Server |
| 5 | +`devcloud` runs a local dashboard plus compatible development endpoints for Mail, S3, GCS, and DynamoDB. It is designed for deterministic local tests and manual inspection, not for production workloads or full cloud-provider parity. |
6 | 6 |
|
7 | | -Start the local SMTP server and Web UI: |
| 7 | +## Quick Start |
| 8 | + |
| 9 | +Initialize local configuration and start all enabled services: |
8 | 10 |
|
9 | 11 | ```bash |
| 12 | +go run ./cmd/devcloud init |
10 | 13 | go run ./cmd/devcloud up |
11 | 14 | ``` |
12 | 15 |
|
13 | 16 | Open the dashboard: |
14 | 17 |
|
15 | 18 | ```text |
16 | | -http://127.0.0.1:8025/mail |
| 19 | +http://127.0.0.1:8025/ |
| 20 | +http://127.0.0.1:8025/dashboard/ |
17 | 21 | ``` |
18 | 22 |
|
19 | | -Send mail to: |
| 23 | +Default local endpoints: |
20 | 24 |
|
21 | | -```text |
22 | | -127.0.0.1:1025 |
23 | | -``` |
| 25 | +| Service | Endpoint | Dashboard | |
| 26 | +| --- | --- | --- | |
| 27 | +| Mail SMTP | `127.0.0.1:1025` | `http://127.0.0.1:8025/mail` | |
| 28 | +| S3 | `http://127.0.0.1:4566` | `http://127.0.0.1:8025/s3` | |
| 29 | +| GCS | `http://127.0.0.1:4443` | `http://127.0.0.1:8025/gcs` | |
| 30 | +| DynamoDB | `http://127.0.0.1:8000` | `http://127.0.0.1:8025/dashboard/dynamodb` | |
24 | 31 |
|
25 | 32 | Useful commands: |
26 | 33 |
|
27 | 34 | ```bash |
| 35 | +go run ./cmd/devcloud help |
28 | 36 | go run ./cmd/devcloud init |
| 37 | +go run ./cmd/devcloud up |
29 | 38 | go run ./cmd/devcloud dashboard |
30 | 39 | go run ./cmd/devcloud reset |
31 | 40 | ``` |
32 | 41 |
|
33 | | -## Verification |
| 42 | +## Configuration |
34 | 43 |
|
35 | | -Run unit and integration tests: |
| 44 | +Configuration lives at `.devcloud/config.yaml`. Runtime data is stored under `.devcloud/data` by default. |
36 | 45 |
|
37 | | -```bash |
38 | | -go test ./... |
39 | | -``` |
| 46 | +```yaml |
| 47 | +project: dev |
40 | 48 |
|
41 | | -Run the Mail MVP acceptance gate: |
| 49 | +server: |
| 50 | + smtpPort: 1025 |
| 51 | + dashboardPort: 8025 |
| 52 | + s3Port: 4566 |
| 53 | + gcsPort: 4443 |
| 54 | + dynamodbPort: 8000 |
42 | 55 |
|
43 | | -```bash |
44 | | -VERIFY_STAGE=full bash scripts/mail-autoloop/verify.sh |
45 | | -``` |
| 56 | +auth: |
| 57 | + smtp: |
| 58 | + mode: off |
| 59 | + s3: |
| 60 | + mode: relaxed |
| 61 | + accessKeyId: dev |
| 62 | + secretAccessKey: dev |
| 63 | + gcs: |
| 64 | + mode: relaxed |
| 65 | + project: devcloud |
| 66 | + dynamodb: |
| 67 | + mode: relaxed |
| 68 | + accessKeyId: dev |
| 69 | + secretAccessKey: dev |
46 | 70 |
|
47 | | -Run the S3 implementation loop foundation gate: |
| 71 | +storage: |
| 72 | + path: .devcloud/data |
48 | 73 |
|
49 | | -```bash |
50 | | -VERIFY_STAGE=foundation bash scripts/s3-autoloop/verify.sh |
| 74 | +services: |
| 75 | + mail: |
| 76 | + enabled: true |
| 77 | + maxMessageBytes: 10485760 |
| 78 | + s3: |
| 79 | + enabled: true |
| 80 | + region: us-east-1 |
| 81 | + pathStyle: true |
| 82 | + virtualHostStyle: false |
| 83 | + maxObjectBytes: 5368709120 |
| 84 | + multipart: |
| 85 | + minPartBytes: 5242880 |
| 86 | + gcs: |
| 87 | + enabled: true |
| 88 | + project: devcloud |
| 89 | + location: US |
| 90 | + dynamodb: |
| 91 | + enabled: true |
| 92 | + region: us-east-1 |
| 93 | + billingMode: PAY_PER_REQUEST |
| 94 | + maxItemBytes: 400000 |
| 95 | + maxTables: 256 |
51 | 96 | ``` |
52 | 97 |
|
53 | | -Run the E2E smoke test: |
| 98 | +## Support Matrix |
| 99 | +
|
| 100 | +Legend: |
| 101 | +
|
| 102 | +| Value | Meaning | |
| 103 | +| --- | --- | |
| 104 | +| Yes | Implemented and covered by tests or E2E smoke checks. | |
| 105 | +| Partial | Useful local subset exists, but behavior is not complete provider parity. | |
| 106 | +| No | Not implemented. Requests may fail, be ignored, or return a compatibility error. | |
| 107 | +
|
| 108 | +### Service Availability |
| 109 | +
|
| 110 | +| Capability | Mail | S3 | GCS | DynamoDB | |
| 111 | +| --- | --- | --- | --- | --- | |
| 112 | +| Local endpoint | Yes | Yes | Yes | Yes | |
| 113 | +| Dashboard view | Yes | Yes | Yes | Yes | |
| 114 | +| Persistent local storage | Yes | Yes | Yes | Yes | |
| 115 | +| Configurable port | Yes | Yes | Yes | Yes | |
| 116 | +| Enable/disable via config | Yes | Yes | Yes | Yes | |
| 117 | +| Local relaxed auth mode | N/A | Yes | Yes | Yes | |
| 118 | +| Strict cloud-grade auth/IAM | No | Partial | No | Partial | |
| 119 | +
|
| 120 | +### Mail |
| 121 | +
|
| 122 | +| Feature | Status | Notes | |
| 123 | +| --- | --- | --- | |
| 124 | +| SMTP receive | Yes | Supports local inbound SMTP for development. | |
| 125 | +| `HELO` / `EHLO`, `MAIL FROM`, `RCPT TO`, `DATA`, `RSET`, `NOOP`, `QUIT` | Yes | Core SMTP smoke path. | |
| 126 | +| Message parsing | Yes | Parses headers, text body, HTML body, and attachments. | |
| 127 | +| Raw RFC 5322 source | Yes | Available through the dashboard API. | |
| 128 | +| Dashboard inbox | Yes | Inspect messages and raw source. | |
| 129 | +| Delete messages | Yes | Single-message and clear-all paths are available through dashboard API. | |
| 130 | +| Outbound relay | No | devcloud is an inbox emulator, not an SMTP relay. | |
| 131 | +| SMTP AUTH | No | Default `auth.smtp.mode` is `off`. | |
| 132 | +| TLS / STARTTLS | No | Local plaintext development endpoint only. | |
| 133 | +| IMAP / POP3 | No | Not implemented. | |
| 134 | + |
| 135 | +### S3-Compatible API |
| 136 | + |
| 137 | +| Feature | Status | Notes | |
| 138 | +| --- | --- | --- | |
| 139 | +| Path-style bucket/object routes | Yes | Default route model. | |
| 140 | +| Virtual-host style routes | No | Config field exists, but runtime routing is path-style. | |
| 141 | +| List buckets | Yes | `GET /`. | |
| 142 | +| Create, head, list, delete bucket | Yes | Empty-bucket delete is supported. | |
| 143 | +| Get bucket location | Yes | Returns configured region. | |
| 144 | +| Put, head, get, delete object | Yes | Includes metadata and content headers. | |
| 145 | +| Range GET | Yes | Supports byte ranges. | |
| 146 | +| ListObjectsV2 | Yes | Prefix listing is covered. | |
| 147 | +| CopyObject | Yes | Supports copy and metadata replacement. | |
| 148 | +| Content-MD5 validation | Yes | Invalid and mismatched digests return S3-style errors. | |
| 149 | +| Multipart upload | Yes | Create/upload/list/complete/abort local multipart flows. | |
| 150 | +| Presigned URL validation | Yes | Covered for local SigV4 GET. | |
| 151 | +| AWS SigV4 header auth | Partial | Relaxed mode is default; strict mode validates local credentials. | |
| 152 | +| ACLs, bucket policy, IAM | No | Not implemented. | |
| 153 | +| Versioning, lifecycle, replication | No | Not implemented. | |
| 154 | +| SSE/KMS, Object Lock, notifications | No | Not implemented. | |
| 155 | +| S3 Select / inventory / analytics | No | Not implemented. | |
| 156 | + |
| 157 | +### GCS-Compatible JSON API |
| 158 | + |
| 159 | +| Feature | Status | Notes | |
| 160 | +| --- | --- | --- | |
| 161 | +| JSON API bucket routes | Yes | `/storage/v1/b...`. | |
| 162 | +| Create, get, list, delete bucket | Yes | Empty-bucket delete is supported. | |
| 163 | +| Object media upload | Yes | `uploadType=media`. | |
| 164 | +| Object multipart upload | Yes | `uploadType=multipart`. | |
| 165 | +| Object resumable upload | Yes | Session start and final upload are supported. | |
| 166 | +| Object metadata get/list/patch/delete | Yes | Includes generation and metageneration fields. | |
| 167 | +| Object media download | Yes | `/download/storage/v1/...` and `alt=media`. | |
| 168 | +| Range download | Yes | Supports byte ranges. | |
| 169 | +| Copy, rewrite, compose | Yes | Local object-copy workflows. | |
| 170 | +| Preconditions | Yes | Generation/metageneration mismatch returns `412`. | |
| 171 | +| Pagination and prefix filters | Partial | Useful local subset for object listing. | |
| 172 | +| OAuth bearer validation | Partial | Local relaxed modes only; no real Google IAM validation. | |
| 173 | +| XML API | No | JSON API subset only. | |
| 174 | +| IAM/ACLs, retention, lifecycle | No | Not implemented. | |
| 175 | +| Pub/Sub notifications, signed URLs | No | Not implemented. | |
| 176 | + |
| 177 | +### DynamoDB-Compatible API |
| 178 | + |
| 179 | +| Feature | Status | Notes | |
| 180 | +| --- | --- | --- | |
| 181 | +| AWS JSON 1.0 endpoint | Yes | Uses `X-Amz-Target: DynamoDB_20120810.*`. | |
| 182 | +| List/Create/Describe/Update/DeleteTable | Yes | Tables become `ACTIVE` immediately. | |
| 183 | +| AttributeValue shapes | Yes | Supports string, number, binary, bool, null, map, list, and sets. | |
| 184 | +| PutItem/GetItem/UpdateItem/DeleteItem | Yes | Includes condition expression and return value subsets. | |
| 185 | +| Query and Scan | Yes | Supports key conditions, pagination, filters, and projections for local use. | |
| 186 | +| Global secondary indexes | Partial | Queryable local index state for supported projection paths. | |
| 187 | +| Local secondary indexes | Partial | Metadata is accepted; behavior is not full DynamoDB parity. | |
| 188 | +| BatchGetItem / BatchWriteItem | Yes | Local batch subset. | |
| 189 | +| TransactGetItems / TransactWriteItems | Yes | Local transaction subset. | |
| 190 | +| PartiQL ExecuteStatement / BatchExecuteStatement / ExecuteTransaction | Partial | Supported statement subset; unsupported PartiQL is rejected. | |
| 191 | +| TTL | Yes | TTL metadata and expiration are supported locally. | |
| 192 | +| Streams | Partial | Stream metadata, shard iterators, and record reads exist for local inspection. | |
| 193 | +| Backups and restore | Partial | Local backup metadata and restore flow. | |
| 194 | +| Tags and resource policies | Partial | Local metadata only; no IAM enforcement. | |
| 195 | +| DescribeLimits / DescribeEndpoints | Yes | Local compatibility responses. | |
| 196 | +| AWS SigV4 header auth | Partial | Relaxed mode is default; strict mode validates local credentials. | |
| 197 | +| DAX, global tables, autoscaling | No | Not implemented. | |
| 198 | +| Real capacity accounting/throttling | No | Local deterministic behavior, not AWS capacity simulation. | |
| 199 | +| IAM condition enforcement | No | Not implemented. | |
| 200 | + |
| 201 | +### Dashboard API |
| 202 | + |
| 203 | +| Feature | Status | Notes | |
| 204 | +| --- | --- | --- | |
| 205 | +| Service registry | Yes | `GET /api/dashboard/services`. | |
| 206 | +| Mail messages API | Yes | List, fetch detail/raw, delete. | |
| 207 | +| S3 dashboard API | Yes | Bucket/object listing, download links. | |
| 208 | +| GCS dashboard API | Yes | Bucket/object/upload-session inspection. | |
| 209 | +| DynamoDB dashboard API | Yes | Status, tables, table detail, indexes, TTL, streams, items. | |
| 210 | +| Common React dashboard shell | Partial | Shared shell is available under `/dashboard/`; some legacy service pages still exist. | |
| 211 | + |
| 212 | +## Verification |
| 213 | + |
| 214 | +Run all Go tests: |
54 | 215 |
|
55 | 216 | ```bash |
56 | | -scripts/mail-e2e.sh |
| 217 | +go test ./... |
57 | 218 | ``` |
58 | 219 |
|
59 | | -Run the S3 E2E smoke test with `awscli-local`: |
| 220 | +Run acceptance gates: |
60 | 221 |
|
61 | 222 | ```bash |
62 | | -scripts/s3-e2e.sh |
| 223 | +VERIFY_STAGE=full bash scripts/mail-autoloop/verify.sh |
| 224 | +VERIFY_STAGE=full bash scripts/s3-autoloop/verify.sh |
| 225 | +VERIFY_STAGE=full bash scripts/gcs-autoloop/verify.sh |
| 226 | +VERIFY_STAGE=full bash scripts/dynamodb-autoloop/verify.sh |
63 | 227 | ``` |
64 | 228 |
|
65 | | -Keep the S3 server running after the E2E journey so you can inspect the bucket and objects: |
| 229 | +Run E2E smoke tests: |
66 | 230 |
|
67 | 231 | ```bash |
68 | | -E2E_INTERACTIVE=true scripts/s3-e2e.sh |
| 232 | +scripts/mail-e2e.sh |
| 233 | +scripts/s3-e2e.sh |
| 234 | +scripts/gcs-e2e.sh |
| 235 | +scripts/dynamodb-e2e.sh |
69 | 236 | ``` |
70 | 237 |
|
71 | | -Run the E2E script in browser inspection mode. This keeps the server running and leaves the smoke mail visible in the Web UI until `Ctrl-C`. |
| 238 | +Keep a service running after the E2E journey for browser/API inspection: |
72 | 239 |
|
73 | 240 | ```bash |
74 | 241 | E2E_INTERACTIVE=true scripts/mail-e2e.sh |
| 242 | +E2E_INTERACTIVE=true scripts/s3-e2e.sh |
| 243 | +E2E_INTERACTIVE=true scripts/gcs-e2e.sh |
| 244 | +E2E_INTERACTIVE=true E2E_DELETE_DATA=false scripts/dynamodb-e2e.sh |
75 | 245 | ``` |
76 | 246 |
|
77 | | -If the default ports are already in use: |
| 247 | +Override ports when defaults are already in use: |
78 | 248 |
|
79 | 249 | ```bash |
80 | 250 | E2E_INTERACTIVE=true E2E_SMTP_PORT=1125 E2E_DASHBOARD_PORT=8125 scripts/mail-e2e.sh |
81 | 251 | E2E_INTERACTIVE=true E2E_S3_PORT=14566 E2E_DASHBOARD_PORT=18025 E2E_SMTP_PORT=11025 scripts/s3-e2e.sh |
| 252 | +E2E_INTERACTIVE=true E2E_GCS_PORT=14443 E2E_DASHBOARD_PORT=18025 scripts/gcs-e2e.sh |
| 253 | +E2E_INTERACTIVE=true E2E_DYNAMODB_PORT=18000 E2E_DASHBOARD_PORT=18025 scripts/dynamodb-e2e.sh |
82 | 254 | ``` |
83 | 255 |
|
| 256 | +## Project Structure |
| 257 | + |
| 258 | +| Path | Purpose | |
| 259 | +| --- | --- | |
| 260 | +| `cmd/devcloud` | Main CLI entry point. | |
| 261 | +| `cmd/devcloudd` | Daemon entry point wiring. | |
| 262 | +| `internal/app` | Config loading, workspace initialization, and daemon orchestration. | |
| 263 | +| `internal/dashboard` | Local Web UI, React assets, and dashboard APIs. | |
| 264 | +| `internal/services/mail` | SMTP inbox service. | |
| 265 | +| `internal/services/s3` | S3-compatible HTTP service and filesystem-backed object store. | |
| 266 | +| `internal/services/gcs` | GCS JSON API-compatible HTTP service. | |
| 267 | +| `internal/services/dynamodb` | DynamoDB-compatible JSON API service. | |
| 268 | +| `docs/` | Product and compatibility designs. | |
| 269 | +| `mock/` | UI design mocks. | |
| 270 | +| `scripts/*-autoloop/` | Bounded implementation-loop and verification scripts. | |
| 271 | +| `scripts/*-e2e.sh` | End-to-end smoke tests. | |
| 272 | + |
84 | 273 | ## Notes |
85 | 274 |
|
86 | | -- Runtime data is stored under `.devcloud/`. |
87 | | -- `scripts/mail-autoloop/` contains the Codex-driven implementation loop and final verification gate. |
88 | | -- `scripts/s3-autoloop/` contains the Codex-driven implementation loop for the S3-compatible server. |
89 | | -- `mock/mail/` contains the design mock used as the Web UI reference. |
90 | | -- `mock/s3/` contains the S3 Object Explorer design mock. |
| 275 | +- devcloud is a local emulator. It intentionally does not implement cloud IAM, billing, availability, or production security guarantees. |
| 276 | +- Runtime data under `.devcloud/` should not be committed. |
| 277 | +- Default development credentials are `dev/dev` for local S3 and DynamoDB strict-mode smoke tests. |
| 278 | +- Compatibility targets are driven by the scripts and design docs in `docs/`; unsupported provider APIs should be added deliberately with tests. |
0 commit comments