Object Creation Backend API Specification

Overview

This document provides technical API specifications for backend developers implementing object creation functionality. For project coordination and user stories, see API Requirements. For UI/UX requirements, see Frontend Requirements.

1. GraphQL Schema Definitions

A. CREATE_OBJECT - Single Object Creation

mutation CreateObject($input: CreateObjectInput!) {
  createObject(input: $input) {
    id
    name
    shortCode
    isSet
    status
    organization {
      id
      name
    }
    spatialParent {
      id
      name
      spatialPath
    }
    tagData {
      instanceKey
      classKey
      path
      shortCode
      isManufacturerTag
    }
    images {
      id
      url
      isMain
      thumbnailUrl
    }
    createdAt
    updatedAt
  }
}

input CreateObjectInput {
  name: String!
  description: String
  organizationId: ID!
  spatialParentId: ID
  tagInstanceKey: String
  tagClassKey: String
  tagPath: String
  isSet: Boolean = false
  status: String = "active"
  batchId: String
  objectType: String
}

B. BATCH_CREATE_OBJECTS - Mobile Batch Creation

mutation BatchCreateObjects($input: BatchCreateInput!) {
  batchCreateObjects(input: $input) {
    success
    batchId
    totalRequested
    totalCreated
    objects {
      tempId
      id
      name
      shortCode
      status
      tagConflict {
        hasConflict
        conflictType
        existingObjectId
        message
      }
    }
    failed {
      tempId
      error
      code
      retryable
    }
  }
}

input BatchCreateInput {
  sessionId: String!
  organizationId: ID!
  spatialParentId: ID
  objects: [BatchObjectInput!]!
}

input BatchObjectInput {
  tempId: String!
  name: String!
  description: String
  objectType: String
  tagInstanceKey: String
  tagClassKey: String
  tagPath: String
}

C. Set Object Mutations

mutation ConvertToSet($objectId: ID!, $setName: String) {
  convertToSet(objectId: $objectId, setName: $setName) {
    id
    name
    isSet
    originalName
    children {
      id
      name
      shortCode
    }
    tagData {
      instanceKey
      shortCode
    }
  }
}

mutation CreateSetChild($setId: ID!, $input: SetChildInput!) {
  createSetChild(setId: $setId, input: $input) {
    id
    name
    shortCode
    setParent {
      id
      name
      isSet
    }
    tagData {
      instanceKey
      shortCode
    }
    tagMigrated
    tagConflict {
      hasConflict
      message
      existingObject {
        id
        name
      }
    }
  }
}

input SetChildInput {
  name: String!
  description: String
  tagInstanceKey: String
  suggestedName: String
}

mutation CompleteSet($setId: ID!) {
  completeSet(setId: $setId) {
    id
    name
    isComplete
    children {
      id
      name
      shortCode
    }
    totalChildren
    completedAt
  }
}

D. Tag Management Mutations

mutation ResolveTagIdentifier($input: TagResolverInput!) {
  resolveTagIdentifier(input: $input) {
    tagData {
      instanceKey
      classKey
      path
      shortCode
      isManufacturerTag
      isGenericTag
    }
    existingObject {
      id
      name
      owner {
        id
        name
      }
      canEdit
      isSet
      setParent {
        id
        name
      }
    }
    conflict {
      hasConflict
      conflictType
      message
      resolutionOptions
    }
    cryptographicValid
  }
}

input TagResolverInput {
  instanceKey: String!
  classKey: String
  path: String
  tagType: String!
}

mutation AssignTagToObject($objectId: ID!, $tagInput: TagAssignmentInput!) {
  assignTagToObject(objectId: $objectId, tagInput: $tagInput) {
    success
    object {
      id
      name
      tagData {
        instanceKey
        shortCode
      }
    }
    tagMigrated
    previousObject {
      id
      name
    }
    auditLog {
      action
      timestamp
      userId
    }
  }
}

input TagAssignmentInput {
  instanceKey: String!
  classKey: String
  path: String
  forceReassign: Boolean = false
}

E. Auto-naming Support

query GenerateObjectName($input: GenerateNameInput!) {
  generateObjectName(input: $input) {
    suggestedName
    isAvailable
    conflictCount
    alternatives {
      name
      isAvailable
    }
  }
}

input GenerateNameInput {
  organizationId: ID!
  baseName: String            # User input or "Object" if empty
  tagShortCode: String        # First 4 chars of tag if present
  preferredPattern: String    # "base", "base (tag)", etc.
}

query CheckNameAvailability($organizationId: ID!, $name: String!) {
  checkNameAvailability(organizationId: $organizationId, name: $name) {
    isAvailable
    conflictCount
    suggestedAlternatives
  }
}

Backend Implementation Requirements:

  1. Name Generation Logic: ```typescript function generateObjectName(input: GenerateNameInput): string { const { organizationId, baseName, tagShortCode } = input;

// Determine base name const base = baseName?.trim() || “Object”;

// Add tag if present const nameWithTag = tagShortCode ? ${base} (${tagShortCode}) : base;

// Check availability and auto-increment return findAvailableName(organizationId, nameWithTag); }

function findAvailableName(orgId: string, baseName: string): string { const existingNames = getObjectNamesInOrganization(orgId);

if (!existingNames.includes(baseName)) { return baseName; }

// Find next available number for (let i = 2; i <= 1000; i++) { const candidate = ${baseName} ${i}; if (!existingNames.includes(candidate)) { return candidate; } }

// Fallback with timestamp if too many conflicts return ${baseName} ${Date.now()}; }


2. **Performance Requirements:**
- **Response Time**: <100ms for name generation
- **Caching**: Cache organization name lists for 5 minutes
- **Batch Support**: Support bulk name generation for batch creation
- **Case Sensitivity**: Case-insensitive duplicate detection

3. **Database Query Optimization:**
```sql
-- Efficient name lookup within organization
SELECT name FROM object_instances 
WHERE organization_id = $1 
  AND LOWER(name) LIKE LOWER($2 || '%')
ORDER BY name;

-- Index for fast name lookups
CREATE INDEX idx_object_names_org_lower 
ON object_instances(organization_id, LOWER(name));

F. Object Class Queries

query SearchObjectClasses($query: String!, $organizationId: ID, $limit: Int = 10) {
  searchObjectClasses(query: $query, organizationId: $organizationId, limit: $limit) {
    id
    name
    description
    manufacturer
    isGeneric
    parentClass {
      id
      name
    }
    usageCount
    recentlyUsed
    matchScore
  }
}

query GetRecentObjectTypes($organizationId: ID!, $limit: Int = 4) {
  getRecentObjectTypes(organizationId: $organizationId, limit: $limit) {
    className
    displayName
    usageCount
    lastUsed
    iconUrl
  }
}

query GetContainerContext($containerId: ID!) {
  getContainerContext(containerId: $containerId) {
    id
    name
    spatialPath
    breadcrumb {
      id
      name
    }
    permissions {
      canCreateObjects
      canCreateSets
    }
    recentObjectTypes
    organization {
      id
      name
    }
  }
}

F. Batch Session Management

query GetBatchSession($sessionId: String!) {
  getBatchSession(sessionId: $sessionId) {
    id
    status
    organizationId
    spatialParentId
    createdBy
    createdAt
    objects {
      tempId
      id
      name
      status
      hasErrors
    }
    totalObjects
    completedObjects
    failedObjects
  }
}

mutation ResumeBatchSession($sessionId: String!) {
  resumeBatchSession(sessionId: $sessionId) {
    session {
      id
      status
      canResume
    }
    pendingObjects {
      tempId
      name
      status
      retryable
    }
  }
}

mutation CompleteBatchSession($sessionId: String!) {
  completeBatchSession(sessionId: $sessionId) {
    success
    session {
      id
      completedAt
      summary {
        totalRequested
        totalCreated
        totalFailed
        duration
      }
    }
  }
}

G. Advanced Object Class Operations

query GetObjectClassHierarchy($classId: ID!) {
  getObjectClassHierarchy(classId: $classId) {
    id
    name
    path
    parentClass {
      id
      name
    }
    childClasses {
      id
      name
      objectCount
    }
    properties {
      name
      type
      required
      defaultValue
      validation
    }
  }
}

mutation CreateObjectClass($input: CreateObjectClassInput!) {
  createObjectClass(input: $input) {
    id
    name
    description
    parentClassId
    properties {
      name
      type
      required
    }
    permissions {
      canEdit
      canDelete
      canCreateInstances
    }
  }
}

input CreateObjectClassInput {
  name: String!
  description: String
  parentClassId: ID
  organizationId: ID!
  properties: [ObjectClassPropertyInput!]
}

input ObjectClassPropertyInput {
  name: String!
  type: PropertyType!
  required: Boolean = false
  defaultValue: String
  validation: PropertyValidationInput
}

enum PropertyType {
  TEXT
  NUMBER
  DATE
  BOOLEAN
  SELECT
  MULTI_SELECT
  URL
  EMAIL
}

H. Advanced Tag Operations

query GetTagHistory($tagInstanceKey: String!) {
  getTagHistory(tagInstanceKey: $tagInstanceKey) {
    assignments {
      objectId
      objectName
      assignedAt
      assignedBy
      removedAt
      removedBy
    }
    scans {
      scannedAt
      scannedBy
      location
      deviceInfo
    }
    conflicts {
      occurredAt
      conflictType
      resolutionAction
      resolvedBy
    }
  }
}

mutation TransferTag($input: TagTransferInput!) {
  transferTag(input: $input) {
    success
    fromObject {
      id
      name
      tagData {
        instanceKey
        shortCode
      }
    }
    toObject {
      id
      name
      tagData {
        instanceKey
        shortCode
      }
    }
    auditLog {
      action
      timestamp
      userId
      reason
    }
  }
}

input TagTransferInput {
  tagInstanceKey: String!
  fromObjectId: ID!
  toObjectId: ID!
  reason: String
  forceTransfer: Boolean = false
}

I. Analytics and Usage Tracking

query GetCreationAnalytics($organizationId: ID!, $timeRange: TimeRange!) {
  getCreationAnalytics(organizationId: $organizationId, timeRange: $timeRange) {
    totalObjects
    dailyCreationCounts {
      date
      count
    }
    topObjectTypes {
      typeName
      count
      percentage
    }
    creationMethods {
      method
      count
      percentage
    }
    averageCreationTime
    taggedObjectsPercentage
    setObjectsCount
  }
}

mutation TrackCreationEvent($input: CreationEventInput!) {
  trackCreationEvent(input: $input) {
    success
    eventId
  }
}

input CreationEventInput {
  objectId: ID!
  eventType: CreationEventType!
  creationMethod: CreationMethod!
  duration: Int
  deviceInfo: String
  metadata: JSON
}

enum CreationEventType {
  OBJECT_CREATED
  BATCH_SESSION_STARTED
  BATCH_SESSION_COMPLETED
  SET_CREATED
  TAG_SCANNED
  IMAGE_UPLOADED
}

enum CreationMethod {
  SINGLE_DESKTOP
  SINGLE_MOBILE
  BATCH_MOBILE
  BULK_IMPORT
  API_DIRECT
}

J. Real-time Subscriptions

subscription ObjectCreated($organizationId: ID!, $spatialParentId: ID) {
  objectCreated(organizationId: $organizationId, spatialParentId: $spatialParentId) {
    id
    name
    shortCode
    status
    createdBy {
      id
      name
    }
    spatialParent {
      id
      name
    }
    isSet
    batchId
    createdAt
  }
}

subscription BatchProgress($batchId: String!) {
  batchProgress(batchId: $batchId) {
    batchId
    totalObjects
    completedObjects
    failedObjects
    currentStatus
    estimatedCompletion
    lastObjectCreated {
      id
      name
    }
  }
}

2. Error Handling

Error Code Enumeration

enum ObjectCreationErrorCode {
  # Tag-related errors
  INVALID_TAG_FORMAT
  TAG_ALREADY_ASSIGNED
  TAG_CONFLICT_DIFFERENT_SET
  TAG_CRYPTOGRAPHIC_INVALID
  
  # Permission errors
  INVALID_ORGANIZATION_ACCESS
  INSUFFICIENT_PERMISSIONS
  INVALID_SPATIAL_PARENT
  
  # Validation errors
  DUPLICATE_OBJECT_NAME
  INVALID_OBJECT_TYPE
  REQUIRED_FIELD_MISSING
  
  # Set operation errors
  SET_CONVERSION_FAILED
  SET_ALREADY_COMPLETE
  INVALID_SET_PARENT
  
  # Batch operation errors
  BATCH_CREATION_FAILED
  BATCH_PARTIAL_FAILURE
  BATCH_SESSION_EXPIRED
  
  # System errors
  IMAGE_REGISTRATION_FAILED
  DATABASE_TRANSACTION_FAILED
  EXTERNAL_SERVICE_UNAVAILABLE
}

Error Response Format

type Error {
  code: ObjectCreationErrorCode!
  message: String!
  field: String
  retryable: Boolean!
  details: ErrorDetails
}

type ErrorDetails {
  conflictingObject: ObjectInfo
  suggestedActions: [String!]
  retryAfter: Int
}

3. Database Schema Changes

Table Modifications

-- Object instances table updates
ALTER TABLE object_instances ADD COLUMN short_code VARCHAR(4);
ALTER TABLE object_instances ADD COLUMN is_set BOOLEAN DEFAULT FALSE;
ALTER TABLE object_instances ADD COLUMN batch_id VARCHAR(50);
ALTER TABLE object_instances ADD COLUMN status VARCHAR(20) DEFAULT 'active';

-- Set relationships table
CREATE TABLE set_relationships (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  parent_set_id UUID REFERENCES object_instances(id),
  child_object_id UUID REFERENCES object_instances(id),
  created_at TIMESTAMP DEFAULT NOW()
);

-- Tag assignments table
CREATE TABLE tag_assignments (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  instance_key VARCHAR(100) UNIQUE NOT NULL,
  class_key VARCHAR(100),
  path VARCHAR(200),
  object_id UUID REFERENCES object_instances(id),
  assigned_at TIMESTAMP DEFAULT NOW(),
  assigned_by UUID REFERENCES auth.users(id)
);

-- Batch sessions table
CREATE TABLE batch_sessions (
  id VARCHAR(50) PRIMARY KEY,
  organization_id UUID REFERENCES organizations(id),
  spatial_parent_id UUID REFERENCES object_instances(id),
  created_by UUID REFERENCES auth.users(id),
  created_at TIMESTAMP DEFAULT NOW(),
  completed_at TIMESTAMP,
  status VARCHAR(20) DEFAULT 'active'
);

-- Object types usage tracking
CREATE TABLE object_type_usage (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  organization_id UUID REFERENCES organizations(id),
  object_type VARCHAR(100),
  usage_count INTEGER DEFAULT 1,
  last_used TIMESTAMP DEFAULT NOW()
);

-- Object class definitions
CREATE TABLE object_classes (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  name VARCHAR(200) NOT NULL,
  description TEXT,
  path VARCHAR(500), -- Hierarchical path: "electronics.computers.laptops"
  parent_class_id UUID REFERENCES object_classes(id),
  organization_id UUID REFERENCES organizations(id), -- NULL for global classes
  is_manufacturer_class BOOLEAN DEFAULT FALSE,
  manufacturer_key VARCHAR(100), -- For cryptographic verification
  created_at TIMESTAMP DEFAULT NOW(),
  created_by UUID REFERENCES auth.users(id),
  is_active BOOLEAN DEFAULT TRUE
);

-- Object class properties
CREATE TABLE object_class_properties (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  class_id UUID REFERENCES object_classes(id),
  name VARCHAR(100) NOT NULL,
  property_type VARCHAR(50) NOT NULL, -- TEXT, NUMBER, DATE, BOOLEAN, SELECT, etc.
  is_required BOOLEAN DEFAULT FALSE,
  default_value TEXT,
  validation_rules JSONB, -- JSON validation rules
  display_order INTEGER DEFAULT 0,
  created_at TIMESTAMP DEFAULT NOW()
);

-- Tag scan history and audit trail
CREATE TABLE tag_scan_events (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  instance_key VARCHAR(100) NOT NULL,
  scanned_by UUID REFERENCES auth.users(id),
  scanned_at TIMESTAMP DEFAULT NOW(),
  scan_location JSONB, -- GPS coordinates, spatial context
  device_info JSONB, -- Device type, app version, etc.
  scan_result VARCHAR(50), -- SUCCESS, CONFLICT, INVALID, etc.
  object_id UUID REFERENCES object_instances(id), -- NULL if conflict/invalid
  ip_address INET,
  user_agent TEXT
);

-- Tag conflict resolution log
CREATE TABLE tag_conflicts (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  instance_key VARCHAR(100) NOT NULL,
  conflict_type VARCHAR(50), -- ALREADY_ASSIGNED, DIFFERENT_SET, etc.
  existing_object_id UUID REFERENCES object_instances(id),
  attempted_object_id UUID REFERENCES object_instances(id),
  occurred_at TIMESTAMP DEFAULT NOW(),
  resolved_at TIMESTAMP,
  resolution_action VARCHAR(50), -- REASSIGN, CANCEL, FORCE, etc.
  resolved_by UUID REFERENCES auth.users(id),
  resolution_reason TEXT
);

-- Creation analytics and metrics
CREATE TABLE creation_events (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  object_id UUID REFERENCES object_instances(id),
  event_type VARCHAR(50) NOT NULL, -- OBJECT_CREATED, BATCH_STARTED, etc.
  creation_method VARCHAR(50) NOT NULL, -- SINGLE_DESKTOP, BATCH_MOBILE, etc.
  organization_id UUID REFERENCES organizations(id),
  created_by UUID REFERENCES auth.users(id),
  occurred_at TIMESTAMP DEFAULT NOW(),
  duration_ms INTEGER, -- Time taken for creation
  device_info JSONB,
  metadata JSONB -- Additional event-specific data
);

-- Batch session detailed tracking
ALTER TABLE batch_sessions ADD COLUMN spatial_parent_name VARCHAR(200);
ALTER TABLE batch_sessions ADD COLUMN device_info JSONB;
ALTER TABLE batch_sessions ADD COLUMN session_metadata JSONB;

-- Enhanced object instances for full feature support
ALTER TABLE object_instances ADD COLUMN class_id UUID REFERENCES object_classes(id);
ALTER TABLE object_instances ADD COLUMN class_properties JSONB; -- Dynamic properties
ALTER TABLE object_instances ADD COLUMN creation_method VARCHAR(50);
ALTER TABLE object_instances ADD COLUMN creation_duration_ms INTEGER;

Performance Indices

-- Short code lookups
CREATE INDEX idx_object_instances_short_code ON object_instances(short_code);

-- Tag assignments
CREATE INDEX idx_tag_assignments_instance_key ON tag_assignments(instance_key);
CREATE INDEX idx_tag_assignments_object_id ON tag_assignments(object_id);

-- Batch operations
CREATE INDEX idx_object_instances_batch_id ON object_instances(batch_id);
CREATE INDEX idx_batch_sessions_organization ON batch_sessions(organization_id);

-- Set relationships
CREATE INDEX idx_set_relationships_parent ON set_relationships(parent_set_id);
CREATE INDEX idx_set_relationships_child ON set_relationships(child_object_id);

-- Usage tracking
CREATE INDEX idx_object_type_usage_org ON object_type_usage(organization_id, last_used DESC);

-- Object class indices
CREATE INDEX idx_object_classes_org ON object_classes(organization_id);
CREATE INDEX idx_object_classes_parent ON object_classes(parent_class_id);
CREATE INDEX idx_object_classes_path ON object_classes(path);
CREATE INDEX idx_object_classes_manufacturer ON object_classes(manufacturer_key);
CREATE UNIQUE INDEX idx_object_classes_name_org ON object_classes(name, organization_id);

-- Object class properties
CREATE INDEX idx_class_properties_class ON object_class_properties(class_id);
CREATE INDEX idx_class_properties_order ON object_class_properties(class_id, display_order);

-- Tag scanning and conflict tracking
CREATE INDEX idx_tag_scan_events_key ON tag_scan_events(instance_key);
CREATE INDEX idx_tag_scan_events_user ON tag_scan_events(scanned_by, scanned_at DESC);
CREATE INDEX idx_tag_scan_events_time ON tag_scan_events(scanned_at DESC);
CREATE INDEX idx_tag_conflicts_key ON tag_conflicts(instance_key);
CREATE INDEX idx_tag_conflicts_time ON tag_conflicts(occurred_at DESC);

-- Creation analytics
CREATE INDEX idx_creation_events_object ON creation_events(object_id);
CREATE INDEX idx_creation_events_org_time ON creation_events(organization_id, occurred_at DESC);
CREATE INDEX idx_creation_events_method ON creation_events(creation_method, occurred_at DESC);
CREATE INDEX idx_creation_events_type ON creation_events(event_type, occurred_at DESC);

-- Enhanced object instances
CREATE INDEX idx_object_instances_class ON object_instances(class_id);
CREATE INDEX idx_object_instances_creation_method ON object_instances(creation_method);

4. Implementation Requirements

A. Short Code Generation Logic

function generateShortCode(tagInstanceKey?: string, organizationId: string): string {
  if (tagInstanceKey) {
    // Extract first 4 characters of Base58-encoded key
    return tagInstanceKey.substring(0, 4);
  } else {
    // Generate sequential number within organization
    const count = getObjectCountInOrganization(organizationId);
    return (count + 1).toString();
  }
}

B. Tag Validation Logic

function validateTag(tagData: TagResolverInput): TagValidationResult {
  // 1. Validate Base58 encoding format
  if (!isValidBase58(tagData.instanceKey)) {
    throw new Error('INVALID_TAG_FORMAT');
  }
  
  // 2. For manufacturer tags: verify classKey authenticity
  if (tagData.classKey) {
    if (!verifyCryptographicSignature(tagData.classKey, tagData.instanceKey)) {
      throw new Error('TAG_CRYPTOGRAPHIC_INVALID');
    }
  }
  
  // 3. Check for existing assignments
  const existingAssignment = findTagAssignment(tagData.instanceKey);
  if (existingAssignment) {
    return { hasConflict: true, existingObjectId: existingAssignment.objectId };
  }
  
  return { hasConflict: false };
}

C. Set Tag Migration Logic

function migrateTagFromSetToChild(setId: string, childId: string, tagInstanceKey: string): void {
  // Check if tag currently points to set
  const currentAssignment = findTagAssignment(tagInstanceKey);
  
  if (currentAssignment?.objectId === setId) {
    // Migrate tag from set to child
    updateTagAssignment(tagInstanceKey, childId);
    logTagMigration(setId, childId, tagInstanceKey);
  } else if (currentAssignment && currentAssignment.objectId !== setId) {
    // Tag points to different object - conflict
    throw new Error('TAG_ALREADY_ASSIGNED');
  }
  // If no current assignment, proceed with normal assignment
}

D. Batch Transaction Safety

async function batchCreateObjects(input: BatchCreateInput): Promise<BatchCreateResult> {
  const transaction = await db.transaction();
  
  try {
    const results = [];
    
    for (const objectInput of input.objects) {
      try {
        const object = await createSingleObject(objectInput, transaction);
        results.push({ success: true, tempId: objectInput.tempId, object });
      } catch (error) {
        results.push({ 
          success: false, 
          tempId: objectInput.tempId, 
          error: error.message,
          retryable: isRetryableError(error)
        });
      }
    }
    
    await transaction.commit();
    return { success: true, results };
    
  } catch (error) {
    await transaction.rollback();
    throw error;
  }
}

5. Performance Requirements

Response Time Targets

  • Single Object Creation: < 1 second
  • Batch Operations: < 5 seconds for 100 objects
  • Tag Resolution: < 200ms
  • Search Queries: < 500ms

Scalability Targets

  • Concurrent Users: 100+ simultaneous object creation
  • Batch Size: Up to 1000 objects per batch
  • Database Load: < 80% CPU during peak usage
  • Memory Usage: < 2GB per backend instance

6. Security Implementation

Authentication Requirements

  • JWT Validation: All mutations require valid JWT token
  • Organization Membership: Verify user belongs to target organization
  • Permission Checking: Validate create_objects permission

Authorization Logic

function validateObjectCreationPermissions(userId: string, organizationId: string): void {
  const membership = getUserOrganizationMembership(userId, organizationId);
  
  if (!membership) {
    throw new Error('INVALID_ORGANIZATION_ACCESS');
  }
  
  if (!membership.permissions.includes('create_objects')) {
    throw new Error('INSUFFICIENT_PERMISSIONS');
  }
}

Data Validation

  • Input Sanitization: All string inputs sanitized for XSS
  • File Validation: Image files validated for type and size
  • SQL Injection Prevention: Parameterized queries only
  • Rate Limiting: Max 100 requests per minute per user

7. REST Endpoint: Image Registration

POST /register-image/{objectId}

interface ImageRegistrationRequest {
  public_url: string;
  storage_path: string;
  is_main?: boolean;
  metadata?: {
    width: number;
    height: number;
    size: number;
    format: string;
    device_info?: string;
  };
}

interface ImageRegistrationResponse {
  success: boolean;
  image: {
    id: string;
    url: string;
    thumbnailUrl: string;
    isMain: boolean;
  };
  object: {
    id: string;
    imageUrls: string[];
    mainImageUrl: string | null;
  };
}


Technical Specification Last Updated: 2025-07-02