Added prominent warnings in multiple locations to prevent accidental
database migrations that would break Impress 2020:
README.md:
- Added critical warning in "OpenNeo ID Database" section
- Highlighted that Impress 2020 directly accesses both databases
- Added warning in "Deployment" section about schema compatibility
- Linked to detailed documentation
docs/impress-2020-dependencies.md:
- Clarified both databases are directly accessed by Impress 2020
- Added new "Database Consolidation Blocker" section
- Documented that consolidation migration is ready but blocked
- Provided options to unblock (retire I2020 or coordinated deployment)
This ensures future developers (including future me!) are aware of this
critical dependency before proposing database schema changes.
Related: feature/consolidate-auth-database branch contains a ready-to-go
database consolidation, but it's blocked on Impress 2020 retirement.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Added critical information about database consolidation blocker:
- Impress 2020 directly accesses BOTH openneo_impress and openneo_id databases
- Any database consolidation must wait until Impress 2020 is retired
- Database migration is ready on feature/consolidate-auth-database branch
but is blocked on this dependency
This ensures we don't accidentally deploy the database consolidation
before addressing the Impress 2020 dependency, which would break
authentication for users accessing the site through Impress 2020.
Updated sections:
- Deployment Architecture: Clarified both databases are accessed by I2020
- After Full Migration: Noted database consolidation is ready but blocked
- Added new "Database Consolidation Blocker" section with details
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
First actual feature I'm letting Claude run! We worked the exploration of the updated API together, then it ran with the implementation.
I left this hanging for a long time.... good to finally have it updated!
I'm not sure if this is a Mac-only problem or what, but we were getting incompatible-function-pointer errors when trying to build the RocketAMF C extensions. This fixes that! (Maybe it's like, Mac-only but as of Ruby 3.4 in specific? We're running RocketAMF in production on Ruby 3.4 right now without this. Shrug.)
I'm starting to learn how AI agent stuff works, and a lot of what I'm finding is that rushing them into feature development sets you up for disaster, but that having strong collaboration conversations with helpful context works wonders.
So, I'm starting by creating that context: I had a little "here's the codebase" walkthrough conversation with Claude Code, and it generated these docs as output—which came out solid from the jump, with a few tweaks from me for improved nuance.
My hope is that this can serve both as an improved starting point for human collaborators _and_ if I let future Claude instances play around in here. That's a big theme of what I've found with AI tools so far: don't try to get clever, don't expect the world, just give them the same support you'd give people—and then everybody wins 🤞
Just because I'm poking at archiving again, I'm noticing failures when trying to run the `rails swf_assets:manifests:load` job, something to do with an "unacquired resource" with the connection.
Maybe this is a bug that an update will fix? May as well try!
Oops, I didn't realize that the MySQL function `SUBSTRING_INDEX` always
returns the full string if the split delimiter isn't found.
This meant that, for series names like "Regal", we read the main name as
"Regal" (correct) and the variant name as "Regal" (incorrect).
This caused sort order to be incorrect for some series, e.g.,
- Prismatic Dawn: Regal
- Prismatic Dusk: Regal
- Prismatic Mirage: Regal
- Regal
whereas the main series name is meant to be first, and *does* come first
in cases like "Festive" where the main name sorts before any of the
variant names!
In this change, we update the variant name definition to return an empty
string. That way, when there's no variant name and it's just the main
series, that one sorts to the top of the series variants.
They made a small change to the API call! Fixed now!
The other NC Mall syncing stuff to get current NC cost is broken, but
that seems like a MUCH bigger change, so I won't bother just yet.
Just a small visual cleanup because I happened to click on item trades
today! We don't need to repeat "This Week" a million times. Just output
it for the first row, then hide it for the following. (We still include
it in screen reader output for semantic clarity; this is just a visual
cleanup.)
Before this change, the "Ornamental Lake with Goldies" item would fail
to preview on the item page: the iframe for the animation layer would
display an error page.
The error was:
```
Invalid Content Security Policy script-src: "https://images.neopets.com/cp/items/data/000/000/497/497366_deca9f2827/497366_HTML5 Canvas.js". Directive values must not contain whitespace or semicolons. Please use multiple arguments or other directive methods instead. (ActionDispatch::ContentSecurityPolicy::InvalidDirectiveError)
```
This is because the URL that Neopets sends us for this JS file contains
an unescaped space character. This isn't usually an issue for e.g.
loading a URL in the browser, but it's *not* valid syntax for inclusion
in a Content Security Policy.
In this change, we update our CSP code to parse URLs into
`Addressable::URI` objects, which enables us to call the `normalize!`
method, which fixes oddities like that.
The URL now correctly appears in the CSP as
`https://images.neopets.com/cp/items/data/000/000/497/497366_deca9f2827/497366_HTML5%20Canvas.js`.
Neopets.com recently added some new security rules that, if not
satisfied, cause the request to return 403 Forbidden.
We figured these out through trial and error, and added them to the
`DTIRequests` library, so they would apply to all requests we make.
We also updated our AMFPHP library to use `DTIRequests` as well, as an
easy way to get the same security rules to apply to those requests.
This change was motivated by pet loading being down for the past day or
so, because all pet loading requests were returning 403 Forbidden! Now,
we've fixed it, hooray!
Sigh, the "Valentine Plushie" series is messing with me again! It
doesn't follow the previously established pattern of the names being
"<series> <color> <species>", because in this case the base color is
considered "Valentine".
Okay, well! In this change we add `full_name` as an explicit database
field, and set the previous full name value as a fallback. (We also
extract the generic fallback logic into `ApplicationRecord`, to help us
express it more concisely.)
We also tweak `adjective_name` to be able to shorten custom `full_name`
values, too. That way, in the outfit editor, the Styles options show
correct values like "Cherub Plushie" for the "Cherub Plushie Acara".
I also make some changes in the outfit editor to better accommodate the
longer series names, to try to better handle long words but also to
just only use the first word of the series main name anyway. (Currently,
all series main names are one word, except "Valentine Plushie" becomes
"Valentine".)
I don't know how reliably people actually know that we support NC
Styles, because the token items aren't searchable.
In this change, we add a little message to teach people about this
feature, if they search for words that match known styles, or the
colloquial word "token" (even though style token items aren't actually
called that on-site).
Previously, we took the incoming date as just an integer, which was
raising a database error when we attempted to save it to a timestamp
field. Now, we correctly parse it into a timestamp.
I imagine we just haven't run the import manually while there's a real
discount in the records before? Weird!
Idk a clear and concise way to group all these together, *and* include
`rspec-rails` in both development and test as the install instructions
recommend, but omit `webmock` from development.
Not that it matters a lot, I just want to be minimal about the gems we
include, for the sake of clarity.
This formulation is a bit verbose, but I think it's maximally clear and
self-consistent, and I appreciate that. I might change my mind later
though?
Anyway, I mostly just noticed this because of the redundancy where
`webmock`'s `group: :test` I think doesn't do anything? Shrug
Huh okay, looks like maybe the `protocol-http` or `protocol-http2` gem
made non-backwards-compatible changes that broke `async-http`. But
moving to the very latest `async-http` seems to fix it. Okay!
It's been a while, time to update all our minor/patch versions!
When I first ran this, the dev server stopped working entirely, saying:
```
NoMethodError: undefined method `ip_address' for an instance of Socket
```
I traced this back to what seems to be a bug introduced in
`protocol-rack` version `0.11.0`, so I modified the Gemfile to hold us
back from that version in particular. After that, everything is looking
good!
Now that some of these series names are very long (like "Prismatic
Cocoa: Festive"), they can throw off the layout. Let's just use the
shorter one, it's clear enough!
Previously, when opening the pose picker and looking at Styles, the
Cybunny options were sorted like this:
- Default
- Celebratory 25th Anniversary
- Festive Christmas
- Nostalgic Baby
- Nostalgic Blue
- Nostalgic Christmas
- Nostalgic Darigan
- Nostalgic Faerie
- Nostalgic Grey
- Nostalgic Maraquan
- Nostalgic Mutant
- Nostalgic Plushie
- Nostalgic Robot
- Nostalgic Royalboy
- Nostalgic Royalgirl
- Nostalgic Snow
- Nostalgic Tyrannian
- Prismatic Cocoa: Festive Christmas
- Prismatic Cocoa: Nostalgic Christmas
- Prismatic Tinsel: Festive Christmas
- Prismatic Tinsel: Nostalgic Christmas
- Spooky Halloween
Now, they're sorted like this:
- Default
- Celebratory 25th Anniversary
- Nostalgic Baby
- Nostalgic Blue
- Festive Christmas
- Prismatic Cocoa: Festive Christmas
- Prismatic Tinsel: Festive Christmas
- Nostalgic Christmas
- Prismatic Cocoa: Nostalgic Christmas
- Prismatic Tinsel: Nostalgic Christmas
- Nostalgic Darigan
- Nostalgic Faerie
- Nostalgic Grey
- Spooky Halloween
- Nostalgic Maraquan
- Nostalgic Mutant
- Nostalgic Plushie
- Nostalgic Robot
- Nostalgic Royalboy
- Nostalgic Royalgirl
- Nostalgic Snow
- Nostalgic Tyrannian
Note especially the Christmas case, which is all together now! I think
it's also more in line with people's expectations for Halloween to be
alphabetically among the rest, instead of being at the bottom for being
"Spooky".
There's enough styles now that I'm starting to wonder if there's other
UI affordances worth having here, like e.g. only showing (or at least
prioritizing) styles that match the chosen color? But I don't want to
mislead people about compatibility, either.