tina4ruby 3.13.147 → 3.13.148
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/CHANGELOG.md +8 -0
- data/lib/tina4/dispatch_pipeline.rb +14 -2
- data/lib/tina4/session.rb +12 -1
- data/lib/tina4/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5f81aa317ab408c5f85fa182149d2bddf74f76a6dbe0d07eab1346335f2feb18
|
|
4
|
+
data.tar.gz: a877a9d71c42570d719c721427d164581919c15e235e17d366891a5337a7920c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4da03de83c10544ac690ce24d6b951b6ba688fab57fb01cb4cf5a630d1e1d41dd5fbab7397538a2910708409c3fb6fea74285ce84fd74559fb883d83303b66d6
|
|
7
|
+
data.tar.gz: cb21b614d729b774a1d9ec16ada8674cab6663e675a370ed7cb8b3f588b3c038036ba0d43bedcf764f1ab673b117df005e30063d50612ce8ace479300104d127
|
data/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,14 @@ number means the same thing everywhere.
|
|
|
6
6
|
**The authoritative release notes for every shipped version live in the documentation:**
|
|
7
7
|
https://tina4.com/ruby/36-releases
|
|
8
8
|
|
|
9
|
+
## 3.13.148 — 2026-10-05
|
|
10
|
+
|
|
11
|
+
### Session
|
|
12
|
+
- An anonymous request stores no session — a request that never reads or writes session state no longer emits a `Set-Cookie` or persists an empty session record (cross-framework fix, at parity across Python, PHP, Ruby, Node.js).
|
|
13
|
+
|
|
14
|
+
### AI skills
|
|
15
|
+
- `tina4-developer-ruby` skill `updated_for_version` bumped to this release.
|
|
16
|
+
|
|
9
17
|
## 3.13.147 — 2026-10-05
|
|
10
18
|
|
|
11
19
|
### Dev MCP tools (fixes #271)
|
|
@@ -649,12 +649,11 @@ module Tina4
|
|
|
649
649
|
# renamed through TINA4_SESSION_NAME, so the auto-Set-Cookie would be
|
|
650
650
|
# needlessly re-emitted on every request that already carries the renamed
|
|
651
651
|
# cookie. Parity with Python's core/server._init_session cookie_prefix.
|
|
652
|
-
sid = sess.id
|
|
653
652
|
cookie_prefix = "#{Tina4::Session.cookie_name}="
|
|
654
653
|
cookie_val = (ctx.env["HTTP_COOKIE"] || "").split(";").map(&:strip)
|
|
655
654
|
.find { |part| part.start_with?(cookie_prefix) }
|
|
656
655
|
&.slice(cookie_prefix.length..)
|
|
657
|
-
if
|
|
656
|
+
if session_needs_cookie?(sess, cookie_val)
|
|
658
657
|
# Route through Session#cookie_header rather than hand-writing the
|
|
659
658
|
# header, so TINA4_SESSION_SECURE / _SAMESITE / _HTTPONLY / _NAME / _TTL
|
|
660
659
|
# are all honoured and Secure reflects the request scheme. The old
|
|
@@ -666,6 +665,19 @@ module Tina4
|
|
|
666
665
|
[status, headers, body_parts]
|
|
667
666
|
end
|
|
668
667
|
|
|
668
|
+
# Whether the response must carry a session cookie: the session has an id the
|
|
669
|
+
# request did not already send, and it is not a fresh one. A fresh session
|
|
670
|
+
# (minted for this request and never written: a route that only read it, or
|
|
671
|
+
# the replacement for a cookie the store does not know) was not stored, so a
|
|
672
|
+
# cookie for it would name nothing - the next request could not resume it and
|
|
673
|
+
# would be handed another one.
|
|
674
|
+
def session_needs_cookie?(sess, cookie_val)
|
|
675
|
+
sid = sess.id
|
|
676
|
+
return false unless sid && sid != cookie_val
|
|
677
|
+
|
|
678
|
+
!(sess.respond_to?(:fresh?) && sess.fresh?)
|
|
679
|
+
end
|
|
680
|
+
|
|
669
681
|
# Milliseconds since the request entered the pipeline.
|
|
670
682
|
def elapsed_ms(ctx)
|
|
671
683
|
((Process.clock_gettime(Process::CLOCK_MONOTONIC) - ctx.started_at) * 1000).round(3)
|
data/lib/tina4/session.rb
CHANGED
|
@@ -217,7 +217,7 @@ module Tina4
|
|
|
217
217
|
# false) therefore still no-ops, exactly as before; a modified session of
|
|
218
218
|
# any kind still writes.
|
|
219
219
|
def save
|
|
220
|
-
return true
|
|
220
|
+
return true if @id.nil? || fresh?
|
|
221
221
|
|
|
222
222
|
record = @data
|
|
223
223
|
if @stored
|
|
@@ -247,6 +247,17 @@ module Tina4
|
|
|
247
247
|
end
|
|
248
248
|
end
|
|
249
249
|
|
|
250
|
+
# Whether this session is only an id: nothing has stored it and it holds no
|
|
251
|
+
# data. Such a session has no record and needs no cookie, so #save writes
|
|
252
|
+
# nothing for it and the dispatcher sends no cookie for it. It stops being
|
|
253
|
+
# fresh when something is stored in it. Calls that mark a session changed
|
|
254
|
+
# without leaving anything in it (deleting a key it never had, #clear,
|
|
255
|
+
# #regenerate on an empty session) leave it fresh: a record with no data is
|
|
256
|
+
# not a session.
|
|
257
|
+
def fresh?
|
|
258
|
+
!@stored && @data.empty?
|
|
259
|
+
end
|
|
260
|
+
|
|
250
261
|
# Destroy the current session. ENDS the session: the stored record is
|
|
251
262
|
# removed and the id is CLEARED (@id = nil), so a later set()+save() with no
|
|
252
263
|
# new #start has no id to persist under and cannot RESURRECT the just-
|
data/lib/tina4/version.rb
CHANGED
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.148
|
|
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-10-
|
|
11
|
+
date: 2026-10-06 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: sqlite3
|