Class: Rhales::Hydrator

Inherits:
Object
  • Object
show all
Defined in:
lib/rhales/hydrator.rb

Overview

Data Hydrator for RSFC client-side data injection

## RSFC Security Model: Server-to-Client Security Boundary

The Hydrator enforces a critical security boundary between server and client:

### Server Side (Template Rendering)

  • Templates have FULL server context access (like ERB/HAML)

  • Can access user objects, database connections, internal APIs

  • Can access secrets, configuration, authentication state

  • Can process sensitive business logic

### Client Side (Data Hydration)

  • Only data declared in <data> section reaches the browser

  • Creates explicit allowlist like designing a REST API

  • Server-side variable interpolation processes secrets safely

  • JSON serialization validates data structure

### Process Flow

  1. Server processes <data> section with full context access

  2. Variables like {user{user.name} are interpolated server-side

  3. Result is serialized as JSON and sent to client

  4. Client receives only the processed, safe data

### Example “‘rue <data>

"user_name": "{{user.name}",           // Safe: just the name
"theme": "{user{user.theme_preference}"    // Safe: just the theme

} </data> “‘

Server template can access {{user.admin?}} and {{internal_config}}, but client only gets the declared user_name and theme values.

This creates an API-like boundary where data is serialized once and parsed once, enforcing the same security model as REST endpoints.

Note: With the new two-pass architecture, the Hydrator’s role is greatly simplified. All data merging happens server-side in the HydrationDataAggregator, so this class only handles JSON generation for individual templates (used during the aggregation phase).

Defined Under Namespace

Classes: HydrationError, JSONSerializationError

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(parser, context) ⇒ Hydrator

Returns a new instance of Hydrator.



57
58
59
60
61
# File 'lib/rhales/hydrator.rb', line 57

def initialize(parser, context)
  @parser           = parser
  @context          = context
  @window_attribute = parser.window_attribute || 'data'
end

Instance Attribute Details

#contextObject (readonly)

Returns the value of attribute context.



55
56
57
# File 'lib/rhales/hydrator.rb', line 55

def context
  @context
end

#parserObject (readonly)

Returns the value of attribute parser.



55
56
57
# File 'lib/rhales/hydrator.rb', line 55

def parser
  @parser
end

#window_attributeObject (readonly)

Returns the value of attribute window_attribute.



55
56
57
# File 'lib/rhales/hydrator.rb', line 55

def window_attribute
  @window_attribute
end

Class Method Details

.generate(parser, context) ⇒ Object

Convenience method to generate hydration HTML DEPRECATED: Use the two-pass rendering architecture instead



125
126
127
128
# File 'lib/rhales/hydrator.rb', line 125

def generate(parser, context)
  warn "[DEPRECATION] Hydrator.generate is deprecated. Use the two-pass rendering architecture instead."
  new(parser, context).generate_hydration_html
end

.generate_data_hash(parser, context) ⇒ Object

Generate data hash (for internal processing)



136
137
138
# File 'lib/rhales/hydrator.rb', line 136

def generate_data_hash(parser, context)
  new(parser, context).processed_data_hash
end

.generate_json(parser, context) ⇒ Object

Generate only JSON data (for testing or API endpoints)



131
132
133
# File 'lib/rhales/hydrator.rb', line 131

def generate_json(parser, context)
  new(parser, context).process_data_section
end

Instance Method Details

#generate_hydration_htmlObject

This method is now deprecated in favor of the two-pass architecture It’s kept for backward compatibility but will be removed in future versions



65
66
67
68
# File 'lib/rhales/hydrator.rb', line 65

def generate_hydration_html
  warn "[DEPRECATION] Hydrator#generate_hydration_html is deprecated. Use the two-pass rendering architecture instead."
  ""
end

#process_data_sectionObject

Process <data> section and return JSON string



71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/rhales/hydrator.rb', line 71

def process_data_section
  data_content = @parser.section('data')
  return '{}' unless data_content

  # Process variable interpolations in the data section
  processed_content = process_data_variables(data_content)

  # Validate and return JSON
  validate_json(processed_content)
  processed_content
rescue JSON::ParserError => ex
  raise JSONSerializationError, "Invalid JSON in data section: #{ex.message}"
end

#processed_data_hashObject

Get processed data as Ruby hash (for internal use)



86
87
88
89
90
91
# File 'lib/rhales/hydrator.rb', line 86

def processed_data_hash
  json_string = process_data_section
  JSON.parse(json_string)
rescue JSON::ParserError => ex
  raise JSONSerializationError, "Cannot parse processed data as JSON: #{ex.message}"
end