Skip to content

Feburary Project Status Report

It has only been a few weeks since the initial status report, but there’s plenty of activity to report on. The goal is to have a monthly update at minimum, but there’s no rule against posting too much!

The big items are: NPC shops are working nicely, and the admin panel is blocked in.

Shops

NPC shops were on deck — they are complete now. Users can purchase a single item at a time1, and purchasing triggers a cooldown. All the “Buy” buttons swap out for a countdown timer when purchasing is on cooldown. This design is inspired by Santae’s restocks, because I found restocking over there to be fun.

The cooldown is determined per-user, so it’s something that you could hook into and adjust. For example, an account unlock could reduce the cooldown period.

There’s a spot in the shop description that will indicate when users can refresh to see new items, with some gently-flashing text. It could trigger the page refresh, but I opted not do have it do that — users can try and slip their last-second purchases in. As long as the item in question is available in new inventory, it will correctly process the transaction, and they’ll feel like they sniped a deal before it expired.

Admin Panel

The lion’s share of the work lately has been on the admin panel. As I indicated before, Kitto² uses Filament, which is an excellent tool for rapidly generating backend CRUD2 screens. It understands Eloquent, model relationships, and authorization policies, so it hooks right in to the code powering the rest of the site.

The whole thing is permission-based. Out-of-the-box, the permissions aren’t too granular: someone can do all the CRUD for a model, or none of it. The permissions are checked by a policy, which are broken out into a bunch of granular permissions, so there are plenty of ways to hook into this and make adjustments to fit your own needs.

The folks on Discord have seen some early previews of how the panel looks. Here’s a couple screenshots. I will need to make a screencast at some point to showcase it properly.

An admin panel listing two species of pet, with new & edit buttons

The edit page for a pet species, with a bunch of fields and a table of colour records that can be edited too

A modal popup with an async search box for item types, for adding ingredients to a recipe

Remaining Work

The admin panel is blocked in, and it’s good enough for me to continue on to the next major feature. It can manage the game setup and permissions/roles.

The major missing aspect is moderation screens. You can edit some basics about a user, but reports, infractions, viewing inappropriate mail, changing inappropriate pet names, etc all remain outstanding.

There are a few smaller things it needs too. The first is all the spots that accept HTML are just a boring-old <textarea> right now. I will do something about that once I finalize HTML cleaning & the rich editor, since anything changes/decisions for that will be relevant for shop/item/etc descriptions too.

And the second is its homepage. I need to design some widgets for signups, daily active users, and so on. The focus will be on spotting trends for trust & safety — if you have a spike of 1500 signups one morning, maybe that’s a bunch of spam bots. A nice chart can help spot the anomaly.

The upside to Filament is that it’s very simple to continue adding to the panel, so when I realize I’ve missed something or have to add a new models, it’s quick to sort that out.

I am considering whether I want to include the popular Laravel Auditing package, and show the audit log for game configs in the admin panel. It would be an easy way to provide a “oops I busted this item how do I revert” panic button, but how often does that really happen…?

Registration Protections

The registration page from Laravel Jetstream doesn’t offer any protection against spam/bot signups3. Kitto² needs something here, or else drive-by spambots will show up on the forums dumping links for questionable online pharmacies and dubious OnlyFans accounts.

The original Kitto included its own CAPTCHA: a classic transcribe-the-weird-looking-letters field for the registration form. That was effective in 20084, but is almost entirely useless in this era of advanced image-to-text tools & generative AI. Some websites use little logic puzzles, perhaps in concert with an image, instead — but they’re just as trivial to defeat with ChatGPT.

I’ve decided that a determined attacker who wants to make 1,000 accounts on a Kitto² site cannot be effectively stopped with any kind of CAPTCHA, so I won’t try. Kitto² will not ship with a CAPTCHA. This solves the screen reader accessibility problem.

But we can still effectively deter drive-by spammers, and some types of determined attackers. Two protection techniques will be applied:

  1. Hidden honeypot fields will be included in the form, invisible in the web browser, but present in the DOM.

    Spambots for comments/forums are made to be quite general, so they’ll fill in every field of a form to avoid “this field is required!” errors. In many cases, “every field in the form” is “all input elements under the <form> node”.

    Human users would see the honeypot fields to fill out, but the bots will. When those fields are populated, the registration can be blocked.

    This is not 100% effective: there are probably spambots that can detect this situation. As more websites adopt this technique, the spammers will adapt to it. But right now, it sounds like this remains effective for a lot of these bots!

  2. Rate limits by autonomous system number (ASN) will be enforced.

    This mitigation should help with dedicated players trying to sign up a ton of accounts. They’ll expect you to detect 1,000 account signups from a single IP and instead spread the load. Using AWS, DigitalOcean, or some other cheap cloud provider gives them access to a large pool of IPs.

    Every IP address is assigned to a provider, and this information is public. The provider is identified by their ASN. Somebody using AWS Lambda to send 1,000 registrations from 1,000 different IPs would be sending them from one5 ASN.

    This could still be defeated by somebody spreading across a lot of providers, or with access to a DDoS botnet. And they could still create 1,000 accounts — just way more slowly, giving your moderation team time to spot the pattern and react.

ReCAPTCHA or Turnstile

Google ReCAPTCHA v3 and Cloudflare Turnstile are both better than anything I can build into Kitto². Bots will continue to advance, so these tools have a dedicated team focusing entirely on defeating the latest techniques spambots are using to hide.

I don’t know if I want to include support for these out-of-the-box. Their heuristics likely involve considerable data collection/processing about your users. This is falling out of style: people are fed up with being tracked, and other countries are adopting European GDPR-style privacy laws.

And, despite what is probably a considerable amount time spent making these work, the going rate for “CAPTCHA Solver” services is about one US dollar per 1,000 requests. A determined attacker with Patchright will not be stopped by these services — which leaves us right back at ASN rate-limiting being our next-best option.

I am curious what people think, though. Is there value in having an “emergency lever” to activate Turnstile? Reach out to the project team on our socials or talk to owls directly.

Up Next: Social Features

The focus going into March will be blocking out the social parts of Kitto²: friends/blocks, the forums, direct messages, and profiles.

I need to start by thinking through exactly how blocking needs to behave to be most effective. There are a lot of little details to consider: what search results should blocking interact with, for example? And how can I design Kitto² to make it easy for developers to continue the use the same behaviours in the social features they develop?

It’s a good point in time to start working on some of the documentation articles. With the admin panel working, the extensible inventory system is done. It would be good to document how item categories work and how to add your own.

Footnotes

  1. This is a deviation from the original Kitto, which allowed you to purchase items in bulk. That is still entirely possible, but it’s not how it works out of the box.

  2. CRUD is a technical term. It stands for Create, Read, Update, and Delete — the basic operations to manage records.

  3. Email account verification will be required before you can do anything, but I think that’s a solved problem for most attackers.

  4. Albeit totally inaccessible to users who depend on screen readers. Which isn’t very nice.

  5. Ok, AWS might be a bad example. From all their international holding companies and acquisitions, they have about 20 ASNs. I have no idea how many are actively handling traffic for AWS services. But that still gives you something to work with, instead of just 1,000 unique IPs.