Chapter 6 of 8

Phase 3: Protocol

WIA-ART-001 Digital Art Standard - Communication Protocols

6.1 Introduction to Communication Protocols

Phase 3 of the WIA-ART-001 specification defines the communication protocols that enable seamless data exchange between systems implementing the standard. While Phase 1 established the data format and Phase 2 defined the API interfaces, Phase 3 specifies how these components communicate in real-time, ensuring reliable, secure, and efficient transmission of digital art data.

Communication protocols serve as the nervous system of the WIA-ART-001 ecosystem. They define not just what messages look like, but how they're transmitted, authenticated, ordered, and acknowledged. Understanding these protocols is essential for building robust integrations that can handle network latency, connection drops, and high-throughput scenarios.

πŸ”„ Protocol Design Goals
  • Reliability: Messages are guaranteed to be delivered and processed
  • Security: All communications are encrypted and authenticated
  • Efficiency: Minimal overhead for maximum performance
  • Interoperability: Works with existing infrastructure and tools

This chapter covers the complete protocol stack including message formats, transport mechanisms, authentication flows, real-time streaming, and error recovery strategies. Each section builds upon established standards while adding the domain-specific requirements needed for digital art handling.

6.2 Message Format Specification

All WIA-ART-001 protocol messages follow a consistent JSON-based format. This standardization ensures that messages can be easily parsed, validated, and processed across different platforms and programming languages.

6.2.1 Core Message Structure

{
  "version": "1.0",
  "type": "wia-art-001",
  "messageId": "msg_xK9mN3pQr5tV7wY",
  "timestamp": "2025-01-15T10:30:00.123Z",
  "payload": {
    // Message-specific content
  },
  "signature": "sha256:abc123...",
  "metadata": {
    "sender": "client_id",
    "correlationId": "correlation_id",
    "priority": "normal",
    "ttl": 300
  }
}

6.2.2 Message Fields

FieldTypeRequiredDescription
versionstringYesProtocol version (semantic versioning)
typestringYesMessage type identifier
messageIdstringYesUnique message identifier (UUID or custom)
timestampISO 8601YesMessage creation timestamp with milliseconds
payloadobjectYesMessage content (structure varies by type)
signaturestringNoCryptographic signature for verification
metadataobjectNoAdditional routing and processing info

6.2.3 Message Types

// Request/Response Types
artwork.create.request
artwork.create.response
artwork.read.request
artwork.read.response
artwork.update.request
artwork.update.response
artwork.delete.request
artwork.delete.response

// Validation Types
validation.request
validation.response
validation.batch.request
validation.batch.response

// Event Types
event.artwork.created
event.artwork.updated
event.artwork.deleted
event.provenance.added
event.export.completed

// System Types
system.heartbeat
system.ping
system.pong
system.error
system.ack

6.2.4 Payload Examples

// Artwork Creation Request
{
  "version": "1.0",
  "type": "artwork.create.request",
  "messageId": "msg_abc123",
  "timestamp": "2025-01-15T10:30:00.000Z",
  "payload": {
    "title": "Digital Landscape #42",
    "creator": {
      "name": "Artist Name",
      "identifier": "artist-uuid"
    },
    "colorSpace": "Adobe RGB",
    "format": "PNG",
    "dimensions": {
      "width": 4096,
      "height": 3072
    }
  },
  "metadata": {
    "sender": "client_12345",
    "correlationId": "session_xyz",
    "priority": "high"
  }
}

// Artwork Created Event
{
  "version": "1.0",
  "type": "event.artwork.created",
  "messageId": "msg_def456",
  "timestamp": "2025-01-15T10:30:01.234Z",
  "payload": {
    "artworkId": "art_xK9mN3pQr5tV7wY",
    "status": "created",
    "uploadUrl": "https://upload.wia.org/...",
    "expiresAt": "2025-01-15T11:30:00Z"
  },
  "metadata": {
    "correlationId": "session_xyz",
    "triggerMessageId": "msg_abc123"
  }
}

6.3 Transport Mechanisms

WIA-ART-001 supports multiple transport mechanisms to accommodate different integration scenarios, from simple request-response patterns to complex real-time streaming.

6.3.1 HTTPS/REST Transport

The primary transport for synchronous operations, suitable for most integration scenarios.

// Request
POST /api/v1/messages HTTP/1.1
Host: api.wia.org
Content-Type: application/json
Authorization: Bearer <token>
X-Request-ID: req_123456

{
  "version": "1.0",
  "type": "artwork.create.request",
  ...
}

// Response
HTTP/1.1 200 OK
Content-Type: application/json
X-Request-ID: req_123456
X-Response-Time: 45ms

{
  "version": "1.0",
  "type": "artwork.create.response",
  ...
}

6.3.2 WebSocket Transport

For real-time bidirectional communication, event streaming, and long-running operations.

// Connection establishment
const ws = new WebSocket('wss://api.wia.org/art-001/v1/stream');

// Authentication after connection
ws.onopen = () => {
  ws.send(JSON.stringify({
    version: '1.0',
    type: 'system.auth',
    payload: {
      token: 'Bearer wia_art_sk_...',
      subscriptions: ['artwork.*', 'event.*']
    }
  }));
};

// Message handling
ws.onmessage = (event) => {
  const message = JSON.parse(event.data);
  
  switch (message.type) {
    case 'event.artwork.created':
      handleArtworkCreated(message.payload);
      break;
    case 'event.artwork.updated':
      handleArtworkUpdated(message.payload);
      break;
    case 'system.heartbeat':
      // Connection keepalive
      break;
  }
};

// Sending messages
function createArtwork(data) {
  ws.send(JSON.stringify({
    version: '1.0',
    type: 'artwork.create.request',
    messageId: generateMessageId(),
    timestamp: new Date().toISOString(),
    payload: data
  }));
}

6.3.3 WebSocket Connection States

1Connecting - WebSocket handshake in progress
2Authenticating - Sending credentials for verification
3Connected - Ready to send/receive messages
4Reconnecting - Automatic reconnection after disconnect
5Closed - Connection terminated

6.3.4 Server-Sent Events (SSE)

For one-way event streaming when bidirectional communication isn't required.

// Client-side
const eventSource = new EventSource(
  'https://api.wia.org/art-001/v1/events?token=...'
);

eventSource.addEventListener('artwork.created', (event) => {
  const data = JSON.parse(event.data);
  console.log('New artwork:', data.artworkId);
});

eventSource.addEventListener('artwork.updated', (event) => {
  const data = JSON.parse(event.data);
  console.log('Updated artwork:', data.artworkId);
});

// Server-side (example)
GET /art-001/v1/events HTTP/1.1
Accept: text/event-stream

// Response stream
event: artwork.created
data: {"artworkId":"art_123","title":"New Work"}

event: artwork.updated
data: {"artworkId":"art_456","changes":["metadata"]}

6.4 Authentication Protocol

Secure authentication ensures that only authorized clients can access the WIA-ART-001 services. The authentication protocol supports multiple credential types and integrates with the transport layer.

6.4.1 API Key Authentication

// HTTP Header
Authorization: Bearer wia_art_sk_1234567890abcdef

// WebSocket Message
{
  "type": "system.auth",
  "payload": {
    "apiKey": "wia_art_sk_1234567890abcdef"
  }
}

6.4.2 OAuth 2.0 Flow

// Step 1: Authorization Request
GET /oauth/authorize
  ?response_type=code
  &client_id=YOUR_CLIENT_ID
  &redirect_uri=https://yourapp.com/callback
  &scope=art:read art:write
  &state=random_state_string

// Step 2: User Authorization (handled by WIA)

// Step 3: Token Exchange
POST /oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code
&code=AUTHORIZATION_CODE
&redirect_uri=https://yourapp.com/callback
&client_id=YOUR_CLIENT_ID
&client_secret=YOUR_CLIENT_SECRET

// Step 4: Access Token Response
{
  "access_token": "eyJhbGciOiJSUzI1NiIs...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "dGhpcyBpcyBhIHJlZnJlc2g...",
  "scope": "art:read art:write"
}

// Step 5: Token Refresh
POST /oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token
&refresh_token=dGhpcyBpcyBhIHJlZnJlc2g...
&client_id=YOUR_CLIENT_ID
&client_secret=YOUR_CLIENT_SECRET

6.4.3 JWT Token Structure

{
  "header": {
    "alg": "RS256",
    "typ": "JWT",
    "kid": "wia-art-001-key-v1"
  },
  "payload": {
    "iss": "https://auth.wia.org",
    "sub": "user_or_client_id",
    "aud": "https://api.wia.org/art-001",
    "exp": 1705330800,
    "iat": 1705327200,
    "jti": "unique_token_id",
    "scope": "art:read art:write",
    "org": "organization_id",
    "permissions": ["create", "read", "update", "delete"]
  },
  "signature": "..."
}

6.4.4 Session Management

// Session creation
{
  "type": "system.session.create",
  "payload": {
    "token": "jwt_or_api_key",
    "clientInfo": {
      "platform": "web",
      "version": "2.1.0",
      "userAgent": "WIA-SDK/1.0"
    },
    "options": {
      "keepAlive": true,
      "timeout": 3600
    }
  }
}

// Session response
{
  "type": "system.session.created",
  "payload": {
    "sessionId": "sess_abc123",
    "expiresAt": "2025-01-15T14:30:00Z",
    "permissions": ["art:read", "art:write"],
    "quotas": {
      "requestsRemaining": 950,
      "uploadBytesRemaining": 5368709120
    }
  }
}

6.5 Reliability and Error Recovery

Robust error handling and recovery mechanisms ensure reliable operation even under adverse network conditions.

6.5.1 Message Acknowledgment

// Client sends message
{
  "type": "artwork.create.request",
  "messageId": "msg_123",
  "requiresAck": true,
  ...
}

// Server acknowledges receipt
{
  "type": "system.ack",
  "payload": {
    "messageId": "msg_123",
    "status": "received",
    "timestamp": "2025-01-15T10:30:00.050Z"
  }
}

// Later, processing complete
{
  "type": "artwork.create.response",
  "correlationId": "msg_123",
  ...
}

6.5.2 Retry Strategy

class RetryStrategy {
  constructor(config = {}) {
    this.maxRetries = config.maxRetries || 3;
    this.baseDelay = config.baseDelay || 1000;
    this.maxDelay = config.maxDelay || 30000;
    this.backoffMultiplier = config.backoffMultiplier || 2;
  }
  
  async execute(operation) {
    let lastError;
    
    for (let attempt = 0; attempt < this.maxRetries; attempt++) {
      try {
        return await operation();
      } catch (error) {
        lastError = error;
        
        if (!this.isRetryable(error)) {
          throw error;
        }
        
        const delay = Math.min(
          this.baseDelay * Math.pow(this.backoffMultiplier, attempt),
          this.maxDelay
        );
        
        console.log(`Retry ${attempt + 1}/${this.maxRetries} in ${delay}ms`);
        await this.sleep(delay);
      }
    }
    
    throw lastError;
  }
  
  isRetryable(error) {
    return [408, 429, 500, 502, 503, 504].includes(error.status);
  }
}

6.5.3 Connection Recovery

class WebSocketManager {
  constructor(url, options = {}) {
    this.url = url;
    this.reconnectDelay = options.reconnectDelay || 1000;
    this.maxReconnectDelay = options.maxReconnectDelay || 30000;
    this.reconnectAttempts = 0;
    this.messageQueue = [];
  }
  
  connect() {
    this.ws = new WebSocket(this.url);
    
    this.ws.onopen = () => {
      this.reconnectAttempts = 0;
      this.flushMessageQueue();
      this.startHeartbeat();
    };
    
    this.ws.onclose = (event) => {
      if (!event.wasClean) {
        this.scheduleReconnect();
      }
    };
    
    this.ws.onerror = () => {
      this.scheduleReconnect();
    };
  }
  
  scheduleReconnect() {
    const delay = Math.min(
      this.reconnectDelay * Math.pow(2, this.reconnectAttempts),
      this.maxReconnectDelay
    );
    
    this.reconnectAttempts++;
    console.log(`Reconnecting in ${delay}ms (attempt ${this.reconnectAttempts})`);
    
    setTimeout(() => this.connect(), delay);
  }
  
  send(message) {
    if (this.ws.readyState === WebSocket.OPEN) {
      this.ws.send(JSON.stringify(message));
    } else {
      this.messageQueue.push(message);
    }
  }
  
  flushMessageQueue() {
    while (this.messageQueue.length > 0) {
      const message = this.messageQueue.shift();
      this.ws.send(JSON.stringify(message));
    }
  }
}

6.5.4 Idempotency

⚠️ Idempotency Requirements

All write operations must be idempotent to safely handle retries. Include a unique idempotencyKey with each request to prevent duplicate processing.

// Request with idempotency key
{
  "type": "artwork.create.request",
  "messageId": "msg_123",
  "idempotencyKey": "create_user123_artwork42_2025011510",
  "payload": { ... }
}

// Server behavior:
// 1. First request: Process and store result with idempotencyKey
// 2. Retry request: Return cached result without reprocessing
// 3. Key expires after 24 hours

6.6 Streaming Protocols

Streaming protocols enable efficient handling of large files and real-time data transmission.

6.6.1 Chunked Upload Protocol

// Step 1: Initialize upload
{
  "type": "upload.init.request",
  "payload": {
    "filename": "artwork.tiff",
    "size": 157286400,
    "mimeType": "image/tiff",
    "chunkSize": 5242880,
    "checksum": "sha256:abc123..."
  }
}

// Step 2: Receive upload session
{
  "type": "upload.init.response",
  "payload": {
    "uploadId": "up_xyz789",
    "totalChunks": 30,
    "chunkSize": 5242880,
    "uploadUrls": [
      "https://upload.wia.org/up_xyz789/chunk/0",
      "https://upload.wia.org/up_xyz789/chunk/1",
      ...
    ],
    "expiresAt": "2025-01-15T14:30:00Z"
  }
}

// Step 3: Upload chunks (can be parallel)
PUT /up_xyz789/chunk/0
Content-Type: application/octet-stream
Content-Length: 5242880
X-Chunk-Checksum: sha256:chunk0hash

[binary data]

// Step 4: Complete upload
{
  "type": "upload.complete.request",
  "payload": {
    "uploadId": "up_xyz789",
    "chunks": [
      { "index": 0, "checksum": "sha256:chunk0hash" },
      { "index": 1, "checksum": "sha256:chunk1hash" },
      ...
    ]
  }
}

6.6.2 Download Streaming

// Range request support for large files
GET /api/v1/digital-art/art_123/content
Range: bytes=0-5242879

HTTP/1.1 206 Partial Content
Content-Range: bytes 0-5242879/157286400
Content-Length: 5242880
Accept-Ranges: bytes

[binary data]

// Progressive download with progress tracking
class ProgressiveDownloader {
  async download(url, onProgress) {
    const response = await fetch(url);
    const reader = response.body.getReader();
    const contentLength = +response.headers.get('Content-Length');
    
    let receivedLength = 0;
    const chunks = [];
    
    while (true) {
      const { done, value } = await reader.read();
      
      if (done) break;
      
      chunks.push(value);
      receivedLength += value.length;
      
      onProgress({
        loaded: receivedLength,
        total: contentLength,
        percent: (receivedLength / contentLength) * 100
      });
    }
    
    return new Blob(chunks);
  }
}

6.6.3 Real-time Event Streaming

// Subscribe to events
{
  "type": "stream.subscribe.request",
  "payload": {
    "topics": [
      "artwork.created",
      "artwork.updated",
      "provenance.*"
    ],
    "filters": {
      "creator": "artist_uuid",
      "since": "2025-01-15T00:00:00Z"
    }
  }
}

// Receive events
{
  "type": "stream.event",
  "payload": {
    "topic": "artwork.created",
    "timestamp": "2025-01-15T10:30:00Z",
    "data": {
      "artworkId": "art_new123",
      "title": "New Creation",
      "creator": "artist_uuid"
    }
  }
}

// Unsubscribe
{
  "type": "stream.unsubscribe.request",
  "payload": {
    "topics": ["artwork.created"]
  }
}

6.7 Security Protocols

Security is paramount when handling valuable digital art assets. The protocol implements multiple layers of protection.

6.7.1 Transport Security

6.7.2 Message Signing

// Generating signature
const signaturePayload = JSON.stringify({
  messageId: message.messageId,
  timestamp: message.timestamp,
  type: message.type,
  payload: message.payload
});

const signature = crypto
  .createHmac('sha256', apiSecret)
  .update(signaturePayload)
  .digest('hex');

message.signature = `sha256:${signature}`;

// Verifying signature (server-side)
function verifySignature(message, apiSecret) {
  const receivedSignature = message.signature;
  const [algorithm, hash] = receivedSignature.split(':');
  
  const calculatedSignature = crypto
    .createHmac(algorithm, apiSecret)
    .update(JSON.stringify({
      messageId: message.messageId,
      timestamp: message.timestamp,
      type: message.type,
      payload: message.payload
    }))
    .digest('hex');
  
  return crypto.timingSafeEqual(
    Buffer.from(hash),
    Buffer.from(calculatedSignature)
  );
}

6.7.3 Request Validation

// Timestamp validation (prevent replay attacks)
const MAX_CLOCK_SKEW = 300; // 5 minutes

function validateTimestamp(timestamp) {
  const messageTime = new Date(timestamp).getTime();
  const currentTime = Date.now();
  const difference = Math.abs(currentTime - messageTime);
  
  if (difference > MAX_CLOCK_SKEW * 1000) {
    throw new Error('Request timestamp too old or in future');
  }
  
  return true;
}

// Nonce tracking (prevent duplicate requests)
const usedNonces = new Set();

function validateNonce(nonce) {
  if (usedNonces.has(nonce)) {
    throw new Error('Duplicate request detected');
  }
  
  usedNonces.add(nonce);
  
  // Clean old nonces periodically
  setTimeout(() => usedNonces.delete(nonce), 300000);
  
  return true;
}

6.8 Chapter Summary

βœ… Key Takeaways
  • Standard JSON message format ensures interoperability across platforms
  • Multiple transport options (HTTP, WebSocket, SSE) support different use cases
  • Robust authentication with API keys, OAuth 2.0, and JWT tokens
  • Built-in reliability with acknowledgments, retries, and idempotency
  • Streaming protocols handle large file transfers efficiently
  • Multiple security layers protect valuable digital art assets

Review Questions

  1. What are the required fields in a WIA-ART-001 protocol message?
  2. When would you choose WebSocket transport over REST?
  3. Explain the purpose of idempotency keys in write operations.
  4. How does the chunked upload protocol handle large files?
  5. What security measures prevent replay attacks?
εΌ˜η›ŠδΊΊι–“

Reliable protocols enable creative expression to flow freely across borders - connecting artists and audiences worldwide.