Repository navigation
Data Model and Storage
classDiagram
direction TB
class Organization {
+UUID id
+String name
}
class User {
+UUID id
+String email
+Role role
+authenticate() bool
}
class Role {
<<enumeration>>
USER
ON_SITE_ADMIN
}
class Site {
+UUID id
+String name
+String address
}
class Robot {
+UUID id
+String serialNumber
+RobotStatus status
+isOnline() bool
}
class Session {
+UUID id
+SessionMode mode
+SessionStatus status
+String videoStorageKey
+start() void
+end() void
}
class SessionMode {
<<enumeration>>
AUTONOMOUS
LIVE_WALKTHROUGH
}
class Mesh {
+UUID id
+MeshVisibility visibility
+String objectStorageKey
+String tilesetKey
+int version
+getSignedUrl() String
}
class Annotation {
+UUID id
+Geometry position
+String label
+Severity severity
}
class Measurement {
+UUID id
+float valueMeters
}
class InspectionReport {
+UUID id
+String pdfStorageKey
+generate() void
}
class ScheduledInspection {
+UUID id
+DateTime runAt
+createJob() InspectionJob
}
class InspectionJob {
+UUID id
+JobStatus status
+store() void
+notifyRobot() void
}
Organization "1" --> "*" User : employs
Organization "1" --> "*" Site : owns
Organization "1" --> "*" Robot : owns
User "1" --> "0..*" Session : operates
Site "1" --> "*" Session : hosts
Site "1" --> "0..1" Robot : assigned
Robot "1" --> "*" Session : performs
Session "1" --> "0..1" Mesh : produces
Mesh "0..1" --> "0..1" Mesh : previousVersion
Mesh "1" --> "*" Annotation : has
Mesh "1" --> "*" Measurement : has
User "1" --> "*" Annotation : authors
Session "1" --> "0..1" InspectionReport : generates
Site "1" --> "*" ScheduledInspection : schedules
Robot "1" --> "*" ScheduledInspection : target
ScheduledInspection "1" --> "0..1" InspectionJob : creates
InspectionJob "1" --> "0..1" Session : resultsIn
User ..> Role : role
Session ..> SessionMode : mode
classDiagram
direction TB
class Organization {
name
}
class User {
email
role
}
class Site {
name
address
}
class Robot {
serialNumber
status
}
class Session {
mode
status
startedAt
endedAt
}
class Mesh {
<<3D Map>>
visibility
version
objectStorageKey
}
class Annotation {
label
severity
position
}
class Measurement {
type
valueMeters
}
class InspectionReport {
title
generatedAt
}
class ScheduledInspection {
runAt
status
}
class InspectionJob {
status
}
Organization "1" --> "*" User : employs
Organization "1" --> "*" Site : owns
Organization "1" --> "*" Robot : owns
User "1" --> "0..*" Session : operates
Site "1" --> "*" Session : hosts
Site "1" --> "0..1" Robot : assigned
Robot "1" --> "*" Session : performs
Session "1" --> "0..1" Mesh : produces
Mesh "0..1" --> "0..1" Mesh : previousVersion
Mesh "1" --> "*" Annotation : has
Mesh "1" --> "*" Measurement : has
User "1" --> "*" Annotation : authors
User "1" --> "*" Measurement : authors
Session "1" --> "0..1" InspectionReport : generates
Site "1" --> "*" ScheduledInspection : schedules
Robot "1" --> "*" ScheduledInspection : target
ScheduledInspection "1" --> "0..1" InspectionJob : creates
InspectionJob "1" --> "0..1" Session : resultsIn
Organization — Tenant that owns users, sites, and robots.
User — Signs in to RoamView. Role is User or On-Site Admin.
Site — Physical location. At most one robot is assigned to a site.
Robot — On-site unit. Runs an autonomous inspection or a live walkthrough.
Session — One walkthrough. Mode is autonomous or live walkthrough. Status moves from recording through processing to ready.
Mesh — 3D map from a session. Public or private. previousVersion links maps for compare-mesh-version. File bytes are in object storage; this entity holds the key.
Annotation / Measurement — Pins and distances on a generated mesh.
Inspection report — Summary of a session. PDF is in object storage.
Scheduled inspection / Inspection job — On-site admin books a run; that creates a job; the robot is notified; a completed job becomes a session.
erDiagram
direction TB
organizations {
uuid id PK
string name
string slug
timestamp created_at
}
users {
uuid id PK
uuid org_id FK
string email
string password_hash
string role
timestamp created_at
}
sites {
uuid id PK
uuid org_id FK
string name
string address
geometry footprint
timestamp created_at
}
robots {
uuid id PK
uuid org_id FK
uuid site_id FK
string name
string serial_number
string status
int battery_pct
timestamp last_seen_at
}
sessions {
uuid id PK
uuid site_id FK
uuid robot_id FK
uuid operator_id FK
string mode
string status
string video_storage_key
timestamp started_at
timestamp ended_at
}
meshes {
uuid id PK
uuid session_id FK
uuid previous_mesh_id FK
string visibility
int version
string object_storage_key
string tileset_key
string preview_key
timestamp created_at
}
annotations {
uuid id PK
uuid mesh_id FK
uuid author_id FK
geometry position
string label
string severity
text notes
timestamp created_at
}
measurements {
uuid id PK
uuid mesh_id FK
uuid author_id FK
string type
jsonb points
float value_meters
timestamp created_at
}
reports {
uuid id PK
uuid session_id FK
uuid author_id FK
string title
string pdf_storage_key
timestamp generated_at
}
scheduled_inspections {
uuid id PK
uuid site_id FK
uuid robot_id FK
timestamp run_at
string status
}
inspection_jobs {
uuid id PK
uuid schedule_id FK
uuid session_id FK
string status
}
organizations ||--o{ users : has
organizations ||--o{ sites : owns
organizations ||--o{ robots : owns
sites ||--o| robots : assigned
users ||--o{ sessions : operates
sites ||--o{ sessions : hosts
robots ||--o{ sessions : performs
sessions ||--o| meshes : produces
sessions ||--o| reports : generates
meshes |o--o| meshes : previous_version
meshes ||--o{ annotations : has
meshes ||--o{ measurements : has
users ||--o{ annotations : authors
users ||--o{ measurements : authors
sites ||--o{ scheduled_inspections : schedules
robots ||--o{ scheduled_inspections : target
scheduled_inspections ||--o| inspection_jobs : creates
inspection_jobs ||--o| sessions : results_in
3D maps are not stored as PostgreSQL BLOBs. meshes.object_storage_key and meshes.tileset_key point at object storage. The same pattern applies to sessions.video_storage_key and reports.pdf_storage_key. The API returns a signed URL; the client streams bytes from object storage / CDN.
- PostgreSQL stores structured metadata. Large binaries (3D maps, video, tiles) are stored in object storage and referenced by key.
Crow’s-foot marks show how many rows participate in a relationship.
| Symbol | Meaning |
|---|---|
|| |
Exactly one (required) |
○| |
Zero or one (optional) |
○< |
Zero or more (optional many) |
PK is the primary key (unique id of a row). FK is a foreign key (points at another table’s PK).
RoamView keeps data in two storage systems:
| System | Technology | What it holds | Access pattern |
|---|---|---|---|
| General storage (metadata) | PostgreSQL | Structured, queryable rows: organizations, users, sites, robots, sessions, jobs, meshes, annotations, reports | Small rows, transactional, joined and filtered by the API |
| Object storage (BLOBs) | S3-compatible object store (e.g. AWS S3 / MinIO) | Large binaries: raw photo sets, depth frames, telemetry bags, video, meshes, 3D tilesets, report PDFs | Written once, read many times, streamed to clients through signed URLs / CDN |
Rule: PostgreSQL never stores file bytes. Tables store the object key (the file's path in object storage), as in the ER diagram on Software Architecture. This replaces the "BLOB storage for 3D maps" note in External Libraries.
The task card uses early names. This page uses the names from Software Architecture and the Domain Model.
| Task card term | Name in this model |
|---|---|
| Facility | sites |
| User | users |
| ScanJob | inspection_jobs |
| Tile |
meshes.tileset_key (the tileset's root file). Each tile file exists only in object storage (see 3D tiles) |
The tables from the ER diagram on Software Architecture are unchanged. One table is added, storage_objects, which lists every file in object storage. It does not replace any existing column. It sits alongside them and is matched to them by key (see section 3).
erDiagram
direction TB
organizations {
uuid id PK
string name
string slug
timestamp created_at
}
users {
uuid id PK
uuid org_id FK
string email
string password_hash
string role
timestamp created_at
}
sites {
uuid id PK
uuid org_id FK
string name
string address
geometry footprint
timestamp created_at
}
robots {
uuid id PK
uuid org_id FK
uuid site_id FK
string name
string serial_number
string status
int battery_pct
timestamp last_seen_at
}
sessions {
uuid id PK
uuid site_id FK
uuid robot_id FK
uuid operator_id FK
string mode
string status
string video_storage_key
timestamp started_at
timestamp ended_at
}
meshes {
uuid id PK
uuid session_id FK
uuid previous_mesh_id FK
string visibility
int version
string object_storage_key
string tileset_key
string preview_key
timestamp created_at
}
annotations {
uuid id PK
uuid mesh_id FK
uuid author_id FK
geometry position
string label
string severity
text notes
timestamp created_at
}
measurements {
uuid id PK
uuid mesh_id FK
uuid author_id FK
string type
jsonb points
float value_meters
timestamp created_at
}
reports {
uuid id PK
uuid session_id FK
uuid author_id FK
string title
string pdf_storage_key
timestamp generated_at
}
scheduled_inspections {
uuid id PK
uuid site_id FK
uuid robot_id FK
timestamp run_at
string status
}
inspection_jobs {
uuid id PK
uuid schedule_id FK
uuid session_id FK
string status
}
storage_objects {
uuid id PK
uuid org_id FK
uuid session_id FK "nullable"
string bucket
string object_key UK "matches the *_key columns"
string kind "RGB_SET | DEPTH_SET | TELEMETRY | SLAM_MAP | VIDEO | MESH | TILESET | PREVIEW | REPORT | INTERMEDIATE"
string content_type
bigint size_bytes
string sha256
string status "PENDING | AVAILABLE | ARCHIVED | DELETED"
timestamp expires_at "from retention policy"
timestamp created_at
}
organizations ||--o{ users : has
organizations ||--o{ sites : owns
organizations ||--o{ robots : owns
sites ||--o| robots : assigned
users ||--o{ sessions : operates
sites ||--o{ sessions : hosts
robots ||--o{ sessions : performs
sessions ||--o| meshes : produces
sessions ||--o| reports : generates
meshes |o--o| meshes : previous_version
meshes ||--o{ annotations : has
meshes ||--o{ measurements : has
users ||--o{ annotations : authors
users ||--o{ measurements : authors
sites ||--o{ scheduled_inspections : schedules
robots ||--o{ scheduled_inspections : target
scheduled_inspections ||--o| inspection_jobs : creates
inspection_jobs ||--o| sessions : results_in
organizations ||--o{ storage_objects : "owns files"
sessions |o--o{ storage_objects : "raw capture, video"
The existing *_key columns already say where each file is. storage_objects adds what those columns can't:
| Need | How storage_objects covers it |
|---|---|
| Capacity tracking |
size_bytes per file → total usage per organization, site or session with one query |
| Upload status |
status shows whether an upload is pending, finished, archived or deleted |
| Integrity |
sha256 checks that a file arrived undamaged |
| Retention and cleanup |
expires_at + status drive the lifecycle process (section 3) |
| Raw capture link | Raw photos, depth frames, telemetry and SLAM maps have no column in the existing tables. session_id + kind links them to their session |
-
UNIQUE (bucket, object_key). -
(session_id, kind)to find all files of a session. -
(status, expires_at)for the retention sweeper.
Object storage has no tables or foreign keys. Its structure comes from buckets and key prefixes (folders). The diagram shows that structure as entities. Each "attribute" is the key pattern, file format or object metadata.
| Bucket | Content | Access | Lifecycle |
|---|---|---|---|
roamview-raw |
Raw capture from the robot: RGB frames, depth frames, telemetry bag, SLAM map | Write: Ingestion Service. Read: Processing Service only | Standard tier for 30 days → cold/infrequent-access tier → delete at 365 days |
roamview-work |
Processing intermediates (COLMAP sparse model, OpenMVS dense cloud) | Processing Service only | Delete after 7 days |
roamview-assets |
Client-facing 3D data: mesh, tileset + tiles, preview image | Read by clients through signed URLs / CDN | Kept while the mesh is kept (365 days by default, see SP-GU05.03) |
roamview-media |
Session video recordings, inspection report PDFs | Read by clients through signed URLs | Video: 90 days. Reports: 365 days |
Keys use IDs, never names. Renaming a site does not move files. The orgs/{org_id}/ prefix makes per-tenant access policies and usage totals simple.
erDiagram
direction TB
BUCKET {
string name "roamview-raw | -work | -assets | -media"
string region
string encryption "SSE (AES-256)"
string lifecycle_rules
}
ORG_PREFIX {
string key "orgs/{org_id}/"
}
SITE_PREFIX {
string key "orgs/{org_id}/sites/{site_id}/"
}
SESSION_PREFIX {
string key "…/sessions/{session_id}/"
}
CAPTURE_MANIFEST {
string key "…/capture/manifest.json"
json frames "seq, file, timestamp, pose, sha256"
string meta "x-amz-meta-session-id"
}
RGB_FRAME {
string key "…/capture/rgb/{seq:06d}.jpg"
string format "JPEG 3840x2160"
float size_mb "~2.5"
}
DEPTH_FRAME {
string key "…/capture/depth/{seq:06d}.png"
string format "PNG uint16 640x480"
float size_mb "~0.3"
}
TELEMETRY_BAG {
string key "…/telemetry/session.mcap"
string format "ROS 2 MCAP (LiDAR, IMU, odom, tf)"
float size_mb "~0.05 per second"
}
SLAM_MAP {
string key "…/slam/map.pgm + map.yaml"
float size_mb "~1"
}
VIDEO_RECORDING {
string key "…/video/recording.mp4"
string format "H.264 720p30 ~2.5 Mbps"
}
WORK_PREFIX {
string key "…/sessions/{session_id}/work/"
}
SPARSE_MODEL {
string key "…/sparse/ (cameras, images, points3D)"
}
DENSE_CLOUD {
string key "…/dense/scene_dense.ply"
}
MESH_VERSION_PREFIX {
string key "…/meshes/{mesh_id}/v{version}/"
}
MESH_FILE {
string key "…/mesh.glb"
string format "glTF binary, textured"
float size_mb "~150"
}
TILESET_ROOT {
string key "…/tiles/tileset.json"
string format "3D Tiles 1.1"
}
TILE {
string key "…/tiles/{level}/{x}_{y}_{z}.glb"
string format "glTF content per LOD node"
}
PREVIEW {
string key "…/preview.webp"
}
REPORT_PDF {
string key "orgs/{org_id}/reports/{report_id}.pdf"
}
BUCKET ||--o{ ORG_PREFIX : contains
ORG_PREFIX ||--o{ SITE_PREFIX : contains
ORG_PREFIX ||--o{ REPORT_PDF : "contains (media)"
SITE_PREFIX ||--o{ SESSION_PREFIX : "contains (raw, media, work)"
SITE_PREFIX ||--o{ MESH_VERSION_PREFIX : "contains (assets)"
SESSION_PREFIX ||--o| CAPTURE_MANIFEST : "raw"
CAPTURE_MANIFEST ||--|{ RGB_FRAME : lists
CAPTURE_MANIFEST ||--o{ DEPTH_FRAME : lists
SESSION_PREFIX ||--o| TELEMETRY_BAG : "raw"
SESSION_PREFIX ||--o| SLAM_MAP : "raw"
SESSION_PREFIX ||--o| VIDEO_RECORDING : "media"
SESSION_PREFIX ||--o| WORK_PREFIX : "work"
WORK_PREFIX ||--o| SPARSE_MODEL : contains
WORK_PREFIX ||--o| DENSE_CLOUD : contains
MESH_VERSION_PREFIX ||--|| MESH_FILE : contains
MESH_VERSION_PREFIX ||--o| TILESET_ROOT : contains
TILESET_ROOT ||--|{ TILE : references
MESH_VERSION_PREFIX ||--o| PREVIEW : contains
A tileset can hold hundreds or thousands of tile files. A database row per tile would add rows without adding anything the API needs. The client only needs the root tileset.json, and Cesium follows its references to fetch tiles. For that reason:
-
meshes.tileset_keypoints at the roottileset.json, as in the existing ER diagram. -
storage_objectshas one row of kindTILESETfor that root. Itssize_bytesis the total of the wholetiles/prefix. - A signed URL (or CDN signed cookie) is issued for the
tiles/prefix so the client can fetch child tiles.
The raw photo set follows the same approach: one manifest.json row, not one row per frame.
flowchart LR
subgraph PG["PostgreSQL (metadata)"]
SES["sessions<br/>video_storage_key"]
MSH["meshes<br/>object_storage_key · tileset_key · preview_key"]
REP["reports<br/>pdf_storage_key"]
SO[("storage_objects<br/>bucket + object_key<br/>size, sha256, status")]
end
subgraph OS["Object storage"]
RAW["roamview-raw<br/>capture/manifest.json · rgb/* · depth/*<br/>telemetry/session.mcap · slam/map.*"]
WORK["roamview-work<br/>work/sparse · dense"]
AST["roamview-assets<br/>meshes/{id}/v{n}/mesh.glb · tiles/* · preview.webp"]
MED["roamview-media<br/>video/recording.mp4 · reports/{id}.pdf"]
end
SES -- "key = object_key" --> SO
MSH -- "key = object_key" --> SO
REP -- "key = object_key" --> SO
SES -- "session_id (raw capture)" --> SO
SO -. "(bucket, object_key)" .-> RAW
SO -. "(bucket, object_key)" .-> WORK
SO -. "(bucket, object_key)" .-> AST
SO -. "(bucket, object_key)" .-> MED
Links in both directions:
-
Metadata → object: a domain row's
*_keycolumn holds the object key. The same key appears instorage_objects.object_key, which adds size, checksum and status. Raw capture files are found throughstorage_objects.session_id. -
Object → metadata: every object is uploaded with the headers
x-amz-meta-storage-object-id,x-amz-meta-org-idandx-amz-meta-session-id. The key prefix also contains the org, site and session IDs. An orphaned file can therefore be traced back to its rows without a database lookup.
sequenceDiagram
autonumber
participant R as Robot (Pi 5)
participant I as Ingestion Service
participant DB as PostgreSQL
participant S3 as Object Storage
participant P as Processing Service
participant C as Web / Mobile client
R->>I: POST /sessions/{id}/uploads (kind, size, sha256)
I->>DB: INSERT storage_objects (status = PENDING)
I-->>R: pre-signed PUT URL(s)
R->>S3: PUT objects (multipart, resumable)
R->>I: POST /uploads/{object_id}/complete
I->>S3: HEAD object (check size + checksum)
I->>DB: UPDATE storage_objects SET status = AVAILABLE<br/>UPDATE sessions SET video_storage_key, status = PROCESSING
I->>P: enqueue processing for session
P->>S3: GET raw capture, PUT intermediates + mesh + tiles
P->>DB: INSERT storage_objects + meshes (object_storage_key,<br/>tileset_key, preview_key) in one transaction<br/>UPDATE sessions SET status = READY
C->>DB: GET /sites/{id}/meshes (via API, auth + visibility check)
DB-->>C: mesh metadata + short-lived signed URL
C->>S3: GET tileset.json → tiles (via CDN)
-
Upload first, then commit. A
*_keycolumn is only filled once the matchingstorage_objectsrow isAVAILABLE.PENDINGrows older than 24 h are marked failed, and their partial uploads are aborted. -
Orphan sweep (daily). Objects without an
AVAILABLE/ARCHIVEDregistry row are deleted. Registry rows whose object is missing are flagged and reported. -
Deletion is status-driven. Retention sets
expires_at. The sweeper deletes the object, then setsstatus = DELETED. The row is kept for audit and usage history. -
Privacy. Every bucket is private and encrypted at rest. Clients never get bucket credentials, only signed URLs that expire within minutes.
PUBLICmeshes skip the ownership check but still use signed URLs. See Ethics & Accountability.
All figures are estimates from stated assumptions. They should be revisited when hardware tests (Hardware Testing) produce measured values. Units: 1 GB = 1000 MB. Script used: capacity.py.
| Parameter | Value | Source / rationale |
|---|---|---|
| Autonomous inspection length | 30 min (1800 s) | ~6 rooms × T_room = 300 s (SP-GU01.03) |
| Live walkthrough length | 6 min (360 s) | T_max control lease (SP-GU01.03) |
| Photogrammetry keyframe rate | 0.5 fps → 900 frames / inspection | 1 frame every 2 s gives enough overlap for COLMAP at walking speed |
| RGB keyframe | 3840×2160 JPEG, ~2.5 MB | OAK-D Lite IMX214 colour sensor (max 4208×3120, 4K30) |
| Depth frame | 640×480 uint16 PNG, ~0.3 MB | OAK-D Lite stereo pair; 614 KB raw, ~50% lossless compression |
| Telemetry bag (MCAP, zstd) | ~0.05 MB/s | Waveshare D500: 5000 samples/s at 10 Hz → ~40 KB/s raw, plus IMU/odom/tf, ~2:1 compression |
| Video recording | 720p30 H.264, 2.5 Mbps | Pi Camera Module 3 Wide. The Pi 5 has no hardware H.264 encoder, so software encoding at 720p is the safe baseline |
| Intermediate files | ~1 GB / inspection | COLMAP sparse model + OpenMVS dense point cloud |
| Textured mesh | ~150 MB | ~1M faces + textures, .glb
|
| 3D tileset | 4/3 × mesh ≈ 200 MB | Quadtree LOD pyramid: 1 + ¼ + 1⁄16 + … = 4/3 |
| Preview / report PDF | 0.5 MB / 5 MB | — |
| Retention | Raw 365 d (hot 30 d, then cold) · intermediates 7 d · video 90 d · mesh, tiles, reports 365 d | Proposed policy. Mesh retention to be confirmed by SP-GU05.03 |
| Object class | Bucket | Autonomous (30 min) | Live walkthrough (6 min) |
|---|---|---|---|
| RGB photo set (900 frames) | raw | 2,250 MB | — |
| Depth frames (900) | raw | 270 MB | — |
| Telemetry bag | raw | 90 MB | 18 MB |
| SLAM map | raw | 1 MB | — |
| Video recording | media | 563 MB | 113 MB |
| Intermediates (temporary) | work | 1,000 MB | — |
| Mesh | assets | 150 MB | — |
| 3D tileset | assets | 200 MB | — |
| Preview + report | assets / media | 6 MB | — |
| Total | ≈ 4.5 GB | ≈ 0.13 GB |
The raw RGB photo set is ~50% of each inspection and ~70% of long-term storage. Its retention period is the main factor in the total.
| Scenario | Sites | Sessions / site / week (auto + live) | Sessions / year | Ingest / month | Hot tier | Cold tier | Total | Total + 20% headroom |
|---|---|---|---|---|---|---|---|---|
| A. Capstone demo | 1 | 2 + 3 | 104 + 156 | 40 GB | 81 GB | 252 GB | 333 GB | 400 GB |
| B. Pilot | 10 | 1 + 5 | 521 + 2,607 | 222 GB | 456 GB | 1.3 TB | 1.75 TB | 2.1 TB |
| C. Growth | 100 | 3 + 10 | 15,643 + 52,143 | 6.4 TB | 12.9 TB | 38.3 TB | 51 TB | 62 TB |
Steady state for each class = daily ingest × retention days. Hot tier = everything except raw capture older than 30 days.
Sensitivity: shortening raw retention from 365 to 90 days reduces Scenario B from 1.75 TB to ≈ 0.69 TB. Reprocessing is then only possible within 90 days.
| Item | Estimate |
|---|---|
| Rows per autonomous inspection | ~46 (1 session, 1 mesh, ~11 storage objects, ~20 annotations, ~10 measurements, 1 report, 1 schedule, 1 job) |
| Rows per live walkthrough | ~3 (1 session, 2 storage objects) |
| Average row size (with indexes) | ~300 B × 2 |
| Year-1 size | A: ~3 MB · B: ~19 MB · C: ~0.5 GB |
The metadata database is small at every scenario. One managed PostgreSQL instance with the smallest storage tier (e.g. 20 GB) and daily backups is enough. The design keeps it small because frames and tiles are not stored as rows.
| Item | Estimate |
|---|---|
| Data to upload per autonomous inspection (raw + video) | ~3.2 GB |
| Upload time at 20 Mbps effective Wi-Fi uplink | ~21 min (an input for SP-GU08.02, "Save Video Recording Job Max Time") |
| Local storage needed | 64 GB microSD/NVMe minus ~16 GB OS/ROS → buffer for ~15 inspections if Wi-Fi is down. Local copies are deleted after the upload is confirmed (status = AVAILABLE) |
RoamView Wiki
- Home
- 1. Introduction
- 2. Project Proposal
- 3. Backlog
- 4. Sprint Summaries
- 5. Architecture
- 6. UI Design
- 7. Testing
- 8. Defect Tracking
- 9. Quality Measurements
- 10. Ethics & Accountability