Use Case: Tag Scanning Integration in Object Creation

Created: Mon 07 Jul 2025 12:12:17 CEST
Updated: Wed 09 Jul 2025 09:17:00 CEST - Added dual tag scanning functionality documentation
Updated: Thu 11 Jun 2026 22:13:27 CEST - Added native app scan-first section; corrected GraphQL examples to match implemented API
Document Version: 2.0 - Native iOS scan-first flow + corrected API examples
Security Classification: Internal Technical Documentation
Target Audience: Frontend Developers, iOS Developers, Backend Developers
Author: Paul Wisén

Overview

This document describes the integration of QR code and NFC tag scanning within the object creation workflow. The tag scanning system serves a dual purpose: enabling users to associate physical identifiers with digital objects AND facilitating spatial relationship assignment when objects are created within containers.

Dual Functionality

  1. Tag Association: Link physical QR/NFC identifiers to new digital objects
  2. Spatial Context: When creating objects within containers, scanning existing container tags establishes immediate spatial relationships

User Stories

Primary: Tag Association

As a user, I want to scan QR codes or NFC tags while creating objects so that I can immediately link physical identifiers to my digital objects without a separate tagging step.

Secondary: Spatial Context

As a user, I want to scan container tags during object creation so that I can immediately place new objects in their correct spatial location.

Actors

  • User: Person creating objects with physical identifiers
  • System: Plings application with camera/NFC capabilities
  • Physical Identifier: QR code sticker or NFC tag

Preconditions

  • User has camera permissions enabled (for QR scanning)
  • User has NFC permissions enabled (for NFC scanning)
  • User is in the object creation modal/workflow
  • Physical identifier is available and unassigned

Workflow Diagram

flowchart TD A[User Opens CreateObjectModal] --> B[User Clicks 'Scan Tag' Button] B --> C[Camera Interface Opens] C --> D{Tag Detected?} D -->|No| E[Show Scanner Overlay
Continue Detection] E --> D D -->|Yes| F[Call resolveIdentifier API] F --> G{Tag Status?} G -->|KNOWN_OBJECT| H[Show 'Tag belongs to [Object]' Dialog] H --> I{User in Container?} I -->|Yes| J[Show Spatial Options:
'Set as current location?'
'Set as normal location?'] I -->|No| K[Show General Options:
'View this object?'
'Continue creating new?'] J --> L[Update Spatial Relationships] K --> M[Navigate to Object Detail] G -->|UNKNOWN_SPECIFIC| N[Show 'Unknown Specific Class' Dialog
Pre-fill ObjectClass] G -->|UNKNOWN_GENERAL| O[Show 'Unknown General' Dialog
Generic Creation Options] G -->|ERROR| P[Show Error Message
Allow Retry or Manual Entry] N --> Q[User Chooses 'Create New Object'] O --> Q Q --> R[Continue Object Creation Flow
with Tag Pre-assigned] R --> S[Complete Object Creation
Tag Automatically Linked] L --> T[Spatial Relationship Established] M --> U[View Existing Object] P --> V[Fallback to Manual Entry] style A fill:#e1f5fe style B fill:#fff3e0 style G fill:#f3e5f5 style H fill:#e8f5e8 style N fill:#fff8e1 style O fill:#fff8e1 style P fill:#ffebee

Native App: Scan-First Entry Point

In the native iOS app (Plings-iOS), the scanner is not a button inside a modal — it is the home screen. The app opens directly into an active scan session; no tap is required to begin scanning.

Identifiers are minted independently of objects; an object is materialized lazily on first scan/use. See Identifier–Object Lifecycle. This is why a scanned tag may be valid yet have no object yet — and why “tag existing object” is offered for both generic and class-specific tags.

Inverted Flow

In the web app, scanning is initiated from a creation modal. In the native app, creation is initiated from a scan result. The scanner is the persistent entry point for all object interactions.

flowchart TD A[App opens] --> B[Scanner active — NFC + QR] B --> C{Tag detected} C --> D[Cache lookup — instant] D --> E{Known in cache?} E -->|Yes| F[Render object view immediately] F --> G[resolveIdentifier mutation in background] G --> H[Refresh object data silently] E -->|No| I[resolveIdentifier mutation — foreground] I --> J{API result} J -->|KNOWN_OBJECT| K[Object view] J -->|UNKNOWN_SPECIFIC / UNKNOWN_GENERAL| L[Create flow — tag pre-assigned] J -->|ERROR| M[Retry / error state] style A fill:#e1f5fe style B fill:#fff3e0 style F fill:#e8f5e8 style L fill:#fff8e1 style M fill:#ffebee

NFC in the Native App

iOS requires an explicit NFC session start — the OS does not scan continuously in the background. In Plings-iOS, a single tap on the scan button (always visible, always in reach) starts an NFC session. QR scanning uses the in-app camera and is continuous. In practice:

  • QR: point camera, tag is detected automatically.
  • NFC: one tap → “Hold near tag” prompt → tap tag → result.

Move Flow via Scan

The move flow is also scan-driven: scan the object to move → tap “Flytta” → scan the destination tag → the drag-to-place relationship picker opens with the container pre-populated. The user drags the object to the correct zone (IN / ON / LEFT_OF / RIGHT_OF / ABOVE / UNDER / NEXT_TO) or taps ATTACHED_TO. No manual identifier entry at any point.

Basic Flow

1. Initiate Object Creation

  • Entry Point: User opens CreateObjectModal from Dashboard QuickActions or object grids
  • Initial State: Modal displays with scan button prominently positioned in header area
  • Context Awareness: System detects if user is within a container context

2. Enable Tag Scanning

  • Activation: Single “Scan Tag” button triggers camera interface
  • Dual Purpose Display: Button shows “Scan Tag” with context hint based on creation location
  • Camera Launch: Native camera interface opens with QR/NFC detection overlay

3. Scan Physical Identifier

  • Real-time Detection: System continuously scans for QR codes and NFC tags
  • Visual Feedback: Scanner overlay highlights detected codes with success/error states
  • Capture Confirmation: User receives immediate feedback on successful scan

4. Handle Scan Results

  • Tag Resolution: System calls resolveIdentifier() to determine tag status
  • Branch Logic: Flow diverges based on known vs unknown tag results
  • Context Integration: Known container tags trigger spatial relationship workflows

5. Complete Object Creation

  • Tag Association: New object automatically linked to scanned identifier
  • Multiple Tag Support: Object can accept additional tags for backup/redundancy
  • Spatial Assignment: If container tag scanned, object placed in spatial context
  • Success Confirmation: User sees complete object with tag(s) and location assigned

Alternative Flows

A1: Known Object Tag Scanned

Trigger: Scanning tag that belongs to existing object Dialog Flow:

  1. Recognition: “This tag belongs to [Object Name]”
  2. Context Options:
    • If in container: “Set as current location?” / “Set as normal location?”
    • If general: “View this object?” / “Continue creating new object?”
  3. Spatial Assignment: User can establish immediate spatial relationships

A2: Unknown Tag Format

Trigger: Scanning unrecognized or malformed identifier Error Handling:

  1. Validation Failure: “Tag format not recognized”
  2. Recovery Options: Manual entry, try again, or skip tag assignment
  3. Graceful Degradation: Object creation continues without tag

A3: Tag Already Assigned (Conflict)

Trigger: Scanning tag already linked to different object Conflict Resolution:

  1. Conflict Detection: “This tag is already assigned to [Other Object]”
  2. User Choice: Transfer tag, create without tag, or scan different tag
  3. Audit Trail: All tag reassignments logged for security

A4: Multiple Tag Support

Trigger: Object already has assigned tags Multiple Tag Handling:

  1. Additional Tag Assignment: “Add this tag as backup/secondary identifier?”
  2. Tag Type Selection: Choose tag role (primary, backup, verification, etc.)
  3. Tag Management: Display all assigned tags with their purposes

Technical Implementation

Frontend Components

  • ScanButton: Primary scan trigger in CreateObjectModal header
  • CameraInterface: QR/NFC detection overlay with visual feedback
  • TagResolutionDialog: Handles known/unknown tag workflows
  • SpatialContextPrompt: Manages spatial relationship assignment dialogs

GraphQL Integration

# Core tag resolution — this is a MUTATION, not a query.
# The gateway and native apps both call this to resolve a scanned tag.
mutation ResolveIdentifier($input: ResolveIdentifierInput!) {
  resolveIdentifier(input: $input) {
    success
    routing {
      action        # REDIRECT | ERROR
      destination
      parameters { key, value }
      cacheTTL
    }
    error { code, message }
  }
}

# Input fields for resolveIdentifier:
# type         String   — tag transport: "q" | "n" | "r" | "b"
# identifier   String   — Base58 instance key from tag URL
# path         String   — HD wallet path from tag URL
# classPointer String?  — optional cp parameter from tag URL
# scanMetadata { timestamp: ISO8601 }

# Object creation with tag pre-assigned
mutation CreateObject($input: CreateObjectInput!) {
  createObject(input: $input) {
    id
    name
    spatialParent { id, name }
  }
}

# CreateObjectInput fields that carry tag data:
#   tagInstanceKey   String   — instance key of the scanned tag
#   tagData {
#     instanceKey    String
#     classKey       String
#     path           String
#     shortCode      String
#     isManufacturerTag Boolean
#   }
#   spatialParentId             String?
#   spatialRelationshipType     SpatialRelationshipType?
#   autoGenerateName            Boolean
# Note: images are NOT included here. Upload them separately after
# the object exists (all object_images rows require an object).

# Image upload — call AFTER createObject succeeds
mutation UploadObjectImages($objectId: ID!, $images: [Upload!]!) {
  uploadObjectImages(objectId: $objectId, images: $images) {
    id
    url
  }
}

Not implemented — proposed only: createObjectWithTag, assignSpatialRelationshipByTag, objectTags query. Do not use these in new code; they do not exist in the API.

# Spatial relationship for CURRENT_* positions
mutation CreateSpatialRelationship($input: CreateSpatialRelationshipInput!) {
  createSpatialRelationship(input: $input) {
    id
    type
    fromObject { id, name }
    toObject { id, name }
  }
}

# Spatial relationship for NORMAL_* (expected) positions
mutation CreateNormalSpatialRelationship($input: CreateNormalSpatialRelationshipInput!) {
  createNormalSpatialRelationship(input: $input) {
    id
    type
    fromObject { id, name }
    toObject { id, name }
  }
}

# Move an object to a new spatial parent
mutation MoveObject($input: MoveObjectInput!) {
  moveObject(input: $input) {
    id
    spatialParent { id, name }
  }
}

Security Considerations

  • Cryptographic Validation: All scanned tags validated against HD wallet signatures
  • Permission Verification: Tag assignment requires edit permissions on target object
  • Audit Logging: All scan events and tag assignments tracked for security analysis

Implementation Status

✅ Currently Available

  • Basic Infrastructure: Camera permissions and QR detection libraries
  • Modal Integration: CreateObjectModal structure supports scan button placement
  • GraphQL Foundation: Core mutations support tag assignment during creation

⚠️ In Development

  • Scan Button Implementation: UI component for scan trigger
  • Camera Interface: QR/NFC detection overlay and user experience
  • Dialog System: Known/unknown tag resolution workflows

❌ Planned Features

  • Advanced Conflict Resolution: Comprehensive tag reassignment workflows
  • Offline Scanning: Queue scanned tags for later processing
  • Manufacturer Integration: Handle pre-registered tag validation
  • Bulk Tag Processing: Batch assign multiple tags during creation

Open Items

  • Finalize scan button placement and visual design
  • Implement camera overlay with detection feedback
  • Define complete dialog flow for all tag resolution scenarios
  • Add spatial relationship assignment via container tag scanning

Last Updated: Thu Jul 10 09:18:47 CEST 2025 - Added multiple tag support documentation and standardized relationship name to IDENTIFIES
Updated: Thu 12 Jun 2026 23:47:35 CEST - Added cross-link to Identifier–Object Lifecycle principle