tina4ruby 3.13.37 → 3.13.38
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/tina4/auth.rb +118 -7
- data/lib/tina4/cli.rb +106 -2
- data/lib/tina4/database.rb +356 -46
- data/lib/tina4/dev_admin.rb +27 -10
- data/lib/tina4/drivers/sqlite_driver.rb +23 -0
- data/lib/tina4/env.rb +40 -4
- data/lib/tina4/events.rb +54 -8
- data/lib/tina4/graphql.rb +68 -12
- data/lib/tina4/html_element.rb +55 -7
- data/lib/tina4/mcp.rb +10 -3
- data/lib/tina4/messenger.rb +130 -25
- data/lib/tina4/metrics.rb +238 -47
- data/lib/tina4/middleware.rb +136 -13
- data/lib/tina4/migration.rb +6 -4
- data/lib/tina4/orm.rb +13 -10
- data/lib/tina4/rack_app.rb +17 -10
- data/lib/tina4/response.rb +31 -11
- data/lib/tina4/seeder.rb +433 -84
- data/lib/tina4/session.rb +94 -17
- data/lib/tina4/version.rb +1 -1
- data/lib/tina4/websocket.rb +354 -18
- data/lib/tina4/wsdl.rb +25 -2
- data/lib/tina4.rb +11 -9
- metadata +6 -47
data/lib/tina4/wsdl.rb
CHANGED
|
@@ -273,6 +273,14 @@ module Tina4
|
|
|
273
273
|
def process_soap(xml_body)
|
|
274
274
|
on_request(@request)
|
|
275
275
|
|
|
276
|
+
# SOAP 1.1 (§3) forbids a Document Type Declaration in a SOAP message.
|
|
277
|
+
# Rejecting any DOCTYPE/DTD up front also closes the XML entity-expansion
|
|
278
|
+
# (billion-laughs) and external-entity (XXE) attack surface — REXML expands
|
|
279
|
+
# internal entities, so a DTD is a live DoS vector. Reject before parsing.
|
|
280
|
+
if xml_body =~ /<!DOCTYPE/i
|
|
281
|
+
return soap_fault("Client", "DOCTYPE declarations are not allowed in SOAP messages")
|
|
282
|
+
end
|
|
283
|
+
|
|
276
284
|
begin
|
|
277
285
|
doc = REXML::Document.new(xml_body)
|
|
278
286
|
rescue REXML::ParseException
|
|
@@ -309,7 +317,12 @@ module Tina4
|
|
|
309
317
|
result = send(op_name.to_sym, *meta[:input].keys.map { |k| params[k.to_s] })
|
|
310
318
|
result = on_result(result)
|
|
311
319
|
rescue StandardError => e
|
|
312
|
-
|
|
320
|
+
# Log the real cause, but only leak the detail to the client in debug
|
|
321
|
+
# mode — a resolver exception can carry internal state (DB credentials,
|
|
322
|
+
# file paths) that must not reach a SOAP client.
|
|
323
|
+
Tina4::Log.error("WSDL operation '#{op_name}' failed: #{e.message}")
|
|
324
|
+
detail = Tina4::Env.is_truthy(ENV["TINA4_DEBUG"]) ? e.message : "Internal server error"
|
|
325
|
+
return soap_fault("Server", detail)
|
|
313
326
|
end
|
|
314
327
|
|
|
315
328
|
soap_response(op_name, result)
|
|
@@ -473,6 +486,11 @@ module Tina4
|
|
|
473
486
|
end
|
|
474
487
|
|
|
475
488
|
def handle_soap_request(xml_body)
|
|
489
|
+
# SOAP 1.1 (§3) forbids a DOCTYPE/DTD. Reject before parsing — this
|
|
490
|
+
# closes the REXML internal-entity expansion (billion-laughs) and XXE
|
|
491
|
+
# surface. Mirrors the class-based process_soap path.
|
|
492
|
+
return _soap_fault("DOCTYPE declarations are not allowed in SOAP messages") if xml_body =~ /<!DOCTYPE/i
|
|
493
|
+
|
|
476
494
|
doc = REXML::Document.new(xml_body)
|
|
477
495
|
|
|
478
496
|
# Find Body element (namespace-agnostic)
|
|
@@ -500,7 +518,12 @@ module Tina4
|
|
|
500
518
|
# Build SOAP response
|
|
501
519
|
_build_soap_response(op_name, result)
|
|
502
520
|
rescue StandardError => e
|
|
503
|
-
|
|
521
|
+
# Mask the real cause in production (parity with process_soap) — a
|
|
522
|
+
# handler exception can carry internal state that must not reach a
|
|
523
|
+
# SOAP client. Detail is logged; only surfaced under TINA4_DEBUG.
|
|
524
|
+
Tina4::Log.error("WSDL operation '#{op_name}' failed: #{e.message}")
|
|
525
|
+
detail = Tina4::Env.is_truthy(ENV["TINA4_DEBUG"]) ? e.message : "Internal server error"
|
|
526
|
+
_soap_fault(detail)
|
|
504
527
|
end
|
|
505
528
|
|
|
506
529
|
private
|
data/lib/tina4.rb
CHANGED
|
@@ -1,13 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
# ── Fast JSON: use oj if available, fall back to stdlib json ──────────
|
|
4
|
-
begin
|
|
5
|
-
require "oj"
|
|
6
|
-
Oj.default_options = { mode: :compat, symbol_keys: false }
|
|
7
|
-
rescue LoadError
|
|
8
|
-
# oj not installed — stdlib json is fine
|
|
9
|
-
end
|
|
10
|
-
|
|
11
3
|
# ── Core (always loaded) ──────────────────────────────────────────────
|
|
12
4
|
require_relative "tina4/version"
|
|
13
5
|
require_relative "tina4/constants"
|
|
@@ -108,6 +100,9 @@ module Tina4
|
|
|
108
100
|
autoload :WebSocket, File.expand_path("tina4/websocket", __dir__)
|
|
109
101
|
autoload :WebSocketConnection, File.expand_path("tina4/websocket", __dir__)
|
|
110
102
|
autoload :DevReload, File.expand_path("tina4/websocket", __dir__)
|
|
103
|
+
autoload :WebSocketBackplane, File.expand_path("tina4/websocket_backplane", __dir__)
|
|
104
|
+
autoload :RedisBackplane, File.expand_path("tina4/websocket_backplane", __dir__)
|
|
105
|
+
autoload :NATSBackplane, File.expand_path("tina4/websocket_backplane", __dir__)
|
|
111
106
|
autoload :Testing, File.expand_path("tina4/testing", __dir__)
|
|
112
107
|
autoload :ScssCompiler, File.expand_path("tina4/scss_compiler", __dir__)
|
|
113
108
|
autoload :FakeData, File.expand_path("tina4/seeder", __dir__)
|
|
@@ -188,13 +183,20 @@ module Tina4
|
|
|
188
183
|
# Print banner
|
|
189
184
|
print_banner
|
|
190
185
|
|
|
191
|
-
# Load environment
|
|
186
|
+
# Load environment. Precedence: real-env > .env.local > .env
|
|
187
|
+
# (.env.local loads first, both first-wins, so a real env var always wins).
|
|
192
188
|
Tina4::Env.load_env(root_dir)
|
|
193
189
|
|
|
194
190
|
# Setup debug logging
|
|
195
191
|
Tina4::Log.configure(root_dir)
|
|
196
192
|
Tina4::Log.info("Tina4 Ruby v#{VERSION} initializing...")
|
|
197
193
|
|
|
194
|
+
# Fail-safe dev secret: in dev (and NOT CI/prod) mint a per-machine
|
|
195
|
+
# random TINA4_SECRET into gitignored .env.local if it is blank; in
|
|
196
|
+
# CI/prod with a blank secret, emit the actionable warning. Runs once at
|
|
197
|
+
# boot after env load, before any auth use. Never crashes boot.
|
|
198
|
+
Tina4::Auth.ensure_dev_secret(root_dir)
|
|
199
|
+
|
|
198
200
|
# Setup auth keys
|
|
199
201
|
Tina4::Auth.setup(root_dir)
|
|
200
202
|
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: tina4ruby
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.13.
|
|
4
|
+
version: 3.13.38
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Tina4 Team
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-06-
|
|
11
|
+
date: 2026-06-19 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rack
|
|
@@ -52,20 +52,6 @@ dependencies:
|
|
|
52
52
|
- - "~>"
|
|
53
53
|
- !ruby/object:Gem::Version
|
|
54
54
|
version: '6.0'
|
|
55
|
-
- !ruby/object:Gem::Dependency
|
|
56
|
-
name: dotenv
|
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
|
58
|
-
requirements:
|
|
59
|
-
- - "~>"
|
|
60
|
-
- !ruby/object:Gem::Version
|
|
61
|
-
version: '3.0'
|
|
62
|
-
type: :runtime
|
|
63
|
-
prerelease: false
|
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
-
requirements:
|
|
66
|
-
- - "~>"
|
|
67
|
-
- !ruby/object:Gem::Version
|
|
68
|
-
version: '3.0'
|
|
69
55
|
- !ruby/object:Gem::Dependency
|
|
70
56
|
name: jwt
|
|
71
57
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -80,20 +66,6 @@ dependencies:
|
|
|
80
66
|
- - "~>"
|
|
81
67
|
- !ruby/object:Gem::Version
|
|
82
68
|
version: '2.7'
|
|
83
|
-
- !ruby/object:Gem::Dependency
|
|
84
|
-
name: bcrypt
|
|
85
|
-
requirement: !ruby/object:Gem::Requirement
|
|
86
|
-
requirements:
|
|
87
|
-
- - "~>"
|
|
88
|
-
- !ruby/object:Gem::Version
|
|
89
|
-
version: '3.1'
|
|
90
|
-
type: :runtime
|
|
91
|
-
prerelease: false
|
|
92
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
93
|
-
requirements:
|
|
94
|
-
- - "~>"
|
|
95
|
-
- !ruby/object:Gem::Version
|
|
96
|
-
version: '3.1'
|
|
97
69
|
- !ruby/object:Gem::Dependency
|
|
98
70
|
name: net-smtp
|
|
99
71
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -136,20 +108,6 @@ dependencies:
|
|
|
136
108
|
- - "~>"
|
|
137
109
|
- !ruby/object:Gem::Version
|
|
138
110
|
version: '2.7'
|
|
139
|
-
- !ruby/object:Gem::Dependency
|
|
140
|
-
name: oj
|
|
141
|
-
requirement: !ruby/object:Gem::Requirement
|
|
142
|
-
requirements:
|
|
143
|
-
- - "~>"
|
|
144
|
-
- !ruby/object:Gem::Version
|
|
145
|
-
version: '3.16'
|
|
146
|
-
type: :runtime
|
|
147
|
-
prerelease: false
|
|
148
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
149
|
-
requirements:
|
|
150
|
-
- - "~>"
|
|
151
|
-
- !ruby/object:Gem::Version
|
|
152
|
-
version: '3.16'
|
|
153
111
|
- !ruby/object:Gem::Dependency
|
|
154
112
|
name: rexml
|
|
155
113
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -277,8 +235,9 @@ dependencies:
|
|
|
277
235
|
- !ruby/object:Gem::Version
|
|
278
236
|
version: '1.50'
|
|
279
237
|
description: 'TINA4: The Intelligent Native Application 4ramework for Ruby — Simple.
|
|
280
|
-
Fast. Human. Built for AI. Built for you. 54 built-in features,
|
|
281
|
-
|
|
238
|
+
Fast. Human. Built for AI. Built for you. 54 built-in features, minimal dependencies
|
|
239
|
+
(Rack-based; the runtime gems are production-deployment essentials, not framework
|
|
240
|
+
bloat). Full parity with Python, PHP, and Node.js.'
|
|
282
241
|
email:
|
|
283
242
|
- info@tina4.com
|
|
284
243
|
executables:
|
|
@@ -460,5 +419,5 @@ requirements: []
|
|
|
460
419
|
rubygems_version: 3.4.19
|
|
461
420
|
signing_key:
|
|
462
421
|
specification_version: 4
|
|
463
|
-
summary: Tina4 for Ruby — 54 built-in features,
|
|
422
|
+
summary: Tina4 for Ruby — 54 built-in features, minimal dependencies
|
|
464
423
|
test_files: []
|