You are browsing as a guest. Sign up (or log in) to start making projects!

F3rro_32

@F3rro_32

Joined June 12th, 2026

  • 26Devlogs
  • 5Projects
  • 3Ships
  • 17Votes
Open comments for this post

43m 27s logged

Just fixed a little bug, the same songs kept coming back whenever you played the same artist twice. That’s because the artist track pool was too small, so every game used it up entirely. I fixed this and also added a nice thing, suggested by @stef. I improved the hints, now it’s easier to guess a song after hints 2 and 3.
I hope you enjoy playing

0
0
3
Open comments for this post

5h 54m 45s logged

Hi guys, here we go again with another devlog.
Lately I worked a lot, so this devlog will be pretty long.
Let’s start with the first piece, the IDT. I made three files: idt.h with the structs and the prototypes, idt.c with the actual table, and idt_flush.s to load it. The table has 256 entries, one for each interrupt vector.

Then I worked on the exceptions raised by the CPU. I created 32 stubs in isr_stubs.s, one for each exception.

I also had to work on the hardware interrupts. I worked in the file io.h, with I/O ports. I used outb and inb, which are inline assembly, for managing ports in C, since C doesn’t have a way for managing them.

Another big part is the PIC 8259 with the remap. When booted, there’s IRQ 0-7 on vectors 8-15. In protected mode there’s already double fault and page fault, so those vectors are already taken. But without remap, when you type a key the kernel sees it as “coprocessor segment overrun”. A problem is that the chip is really old, so it’s older than the numbering it collides with.
There’s one more thing about the PIC, and it’s the end of interrupt. After it sends you an interrupt, it doesn’t send the next ones until you tell it you’re done, by writing 0x20 to its command port. So I have to do that at the end of every IRQ handler. If you forget it you get exactly one interrupt and then nothing, forever, and the annoying part is that nothing looks broken: no error, no crash, the first interrupt works perfectly.

The last piece is how the handler goes back, and it’s probably the most interesting one.
I would have used ret, like in a normal function, but it doesn’t work here. That’s because ret only restores eip, while an interrupt also pushed cs and eflags. Eflags is where the IF flag lives (the one that says if interrupts are enabled or not) and the CPU turns it off by itself when it gives you the interrupt, so that your handler doesn’t get interrupted in the middle.. So with ret interrupts stay off forever and you never get another one.

The solution is iret. And right before it I have to do add esp, 8, because the vector number and the error code were pushed by me, not by the CPU, and iret knows nothing about them.

To test all of this I unmasked IRQ 0, the timer, and I didn’t have to configure the timer at all: the BIOS had already programmed the PIT, so it was ticking the whole time and the interrupts started coming as soon as I enabled them. The screen fills up with IRQ raised: 00. That screenshot proves three things at the same time: the remap worked, because the interrupt arrives on vector 32 and not on 8; the EOI is getting through, otherwise there would be one single line; and iret puts the stack back exactly as it found it, a few hundred times in a row without missing once.

I’m so happy for this work. Look forward for the next steps

0
0
7
Open comments for this post

5h 0m 39s logged

First devlog where the screen looks exactly the same before and after.
Turns out that’s the interesting part: the GDT is the table the CPU reads on every single memory access, and doing it right means nothing visible happens.

What I built

  • A real VGA text driver (vga.c): putchar, write, line wrap, \n, and scrolling. The surprise: there is no hardware scroll in VGA text mode, scrolling means copying all 2000 cells up one row yourself and blanking the last one. I’d always assumed the terminal did that for you, it’s a for loop.

  • The GDT (gdt.c, gdt.h): three entries: a null one (mandatory, so an uninitialized segment register faults immediately instead of doing something random), one for code, one for data. Base 0 and limit 4GB on both, the flat model. You can’t turn segmentation off on x86, so you make it irrelevant instead.

  • Replacing GRUB’s table.: GRUB leaves you a working GDT, otherwise the kernel wouldn’t run at all, but it lives in GRUB’s memory and GRUB is gone. My stack grows, .bss expands, an allocator shows up eventually, and one day something writes over it. From that moment the CPU reads garbage on every memory access.

  • Shift and mask code for a 40 year old compatibility hack.: A descriptor is 8 bytes with the base address split into three non-contiguous chunks and the limit split in two. The 286 had 24 bit addresses in 1982, the 386 needed 8 more bits of base and 4 more of limit and couldn’t move any existing field without breaking every OS already written, so the new bits got wedged into the spare bytes at the end. __attribute__((packed)) isn’t optional here, one byte of padding and the CPU misreads everything.

  • The assembly loader (gdt_flush.s): lgdt plus reloading all five data segment registers, because each one caches the descriptor internally and changing the table doesn’t touch registers already loaded.

  • A jump that goes nowhere.: mov cs, ax does not exist: cs says which segment your code is in and eip says where in it, two halves of one address, so changing only cs lands the next instruction fetch at the old offset inside the new segment. They have to change together, and the only instruction that does that is a far jump. The idiom is jumping to the very next line. I disassembled it to convince myself: the jump sits at 0x15, is 7 bytes long, ends at 0x1c, and its destination is 0x1c. The jump is the vehicle, loading cs is the cargo.

  • Proof that something invisible happened. Nothing changed on screen so I asked the CPU through the QEMU monitor: GDT= 001042f4 00000017, and nm says my table is at 001042f4 with sizeof(gdt) - 1 = 23 = 0x17. CS reads [-R-], readable not writable, DS reads [-WA], writable not executable. I set the data access byte to 0x92 and the CPU reports 93: that’s the accessed bit, hardware turns it on by itself the first time the segment is used.

Look forward for the next steps

0
0
1
Open comments for this post

3h 22m 28s logged

Booted my first kernel today. It’s just a black screen with a white “F” in the corner, but it’s my black screen with my white “F”, printed by code I wrote, with no OS underneath.

What I built

  • A cross-compiler from source. i686-elf-gcc doesn’t exist on a normal Linux install, you build it yourself from binutils + gcc source, targeting a “fake” freestanding platform (no OS, no libc assumed).
    I wrote the whole build script in bash, which I’d genuinely never written before this project.

  • A Multiboot2 header (boot.s, NASM assembly) the exact magic number, checksum, and end tag GRUB looks for to recognize a bootable kernel. Also set up a stack (the CPU doesn’t give you one for free) and the _start entry point that hands off from assembly into C.

  • A linker script (linker.ld) that tells the linker to load the kernel at 1MB — the first chunk of physical memory not already claimed by legacy BIOS/VGA stuff.

  • kernel.c — writes directly to the VGA text buffer at physical address 0xB8000 (2 bytes per character: ASCII + color attribute). No printf, no stdlib, just a raw pointer and a cast.

Look forward for the next steps

0
0
3
Ship

This project contains three microprojects, all related.
There’s the slack_bot, already shipped for the mission.
There’ s the ds_bot, improved from it’s first version in flavortown.
And there’s a newborn, a website, containing everything necessary for the bot, with also docs, for hosting the bot locally.
For making the design of the website, since I’m not that great with graphics, I used v0, which generated mockups for me. That’s why the website Ui seems so AI.

  • 1 devlog
  • 7h
Try project → See source code →
Open comments for this post

6h 42m 57s logged

Spent today hardening VinylBot for production: fixed a crash bug where an unhandled ffmpeg/stream error in the audio player could take down the entire bot for every server at once, added global uncaughtException/unhandledRejection handlers to both bots, fixed a race condition in the Slack round timer, and cleaned up leaked temp mp3 files on failed downloads.

Also dockerized the Angular website (nginx + multi-stage build) and got all three services (Discord bot, Slack bot, website) live on their own subdomains behind the VPS firewall.

For the problem of the streaming on server or vps I decided to add two methods for gathering audio mp3s. The first time it will try with spotify, searching for the preview_url. After that it will try deezer and Itunes, that represents a valid alternative.

0
0
3
Open comments for this post

36m 38s logged

I don’t know why, but the db crashed, so the backend wasn’t working and many of you couldn’t test out the app.
I just fixed this problem, and added in docker compose the restart clause, so things like this won’t happen again.
Sorry for the problem

0
0
3
Open comments for this post

1h 56m 15s logged

Hey guys, today I’m working on fixing the ds bot. First of all I had to review the method of streaming the song.
I was first using yt-dlp for everything, but I noted that putting it on a server was making it not working anymore. I discovered that is because yt blocks certain ips and certain requests, so this was an impossible choice. The solution was spotify preview, which are basically like 20 seconds of a song. That’s perfect for me, since I don’t have to stream the whole song, but instead just a little part.

The approach is this. I created a variable in the env, called DEPLOY_ENV. This specifies if we’re running the bot locally, or on a server or vps.

If the variable is vps, first the bot is gonna try finding the song on spotify. If it’s not present, it’s gonna search for local files, as alternative.

If the variable is local, the first alternative remains spotify, but as a second there’s also yt-dlp, since locally it works fine.

I also adjusted the cards of some commands, as you can see from the screens, along with testing out the bot.

I still have some more work to do, but I think soon the ds bot will be ready.

0
0
5
Open comments for this post

1h 52m 24s logged

As you can see, I’m currently working on fixing some minor details, like improving the card. This card is displayed whenever you use the commands play, nowplaying, pause, skip, previous.

In this card you can see the song, the album it comes from, who requested to see the card and also the timing.
Additionaly there are buttons for pausing, skipping and level up or down the button by 10 units.

I also discovered something I didn’t know. Recently you can use your own emojis, so I generated this one with chatgpt and used them for the commands, as you can see in the card. Really useful

0
0
3
Open comments for this post

4h 34m 24s logged

Hey guys, so I decided to improve this project. I created another repo, containing both the bot in slack, made in this “session”, and the bot made for discord, made in Flavortown.
Along with those two projects, I added a website. So now the repo contains the two bots, and the website.
I just built the website, it’s a simple landing page. For generating mockups for the design I used v0 by vercel, which is really useful for people like me, who aren’t able to produce anything graceful without a designer.

So, as I was saying, the website it’s just a simple landing page, containing infos about the bots, allowing to download the bots and more.

I also added two routes /status and /docs.
The names explain the function. The first oen contains the status of each bots.
The second one contains well-written docs, very useful for people who want to host the bot locally.

0
0
4
Ship

SecureVault, zero knowledge, end-to-end encrypted cloud storage. Your files and their names are encrypted in the browser before they ever reach the server, which only ever stores ciphertext it can’t read.

  • 11 devlogs
  • 35h
  • 9.05x multiplier
  • 318 Stardust
Try project → See source code →
Open comments for this post

1h 16m 23s logged

Finished the project. I used a seo checker to improve the seo, at least, what I can actually improve.
I then focused on writing the md files. The readme and the security.md, that displays all infos about how crypto works and in general terms, security.
I hope you like the project.

0
0
5
Open comments for this post

6h 24m 56s logged

Hey guys, here I am again.

Lately I focused a lot on improving both the website and the overall user experience. The first thing I did was completely redesign the landing page. I switched everything to a dark theme, added a new hero section with a background image and gradient overlay, and converted every section into dark cards to make the design feel much more consistent.
I also reworked the pricing section
Finally, I added smooth navigation between sections using anchor links. I also redesigned the navigation bar. On desktop and tablets it stays at the top as expected, while on mobile it moves to the bottom of the screen for easier access. During this process I removed the old hamburger menu.
The file manager received one of the biggest UI updates. On mobile there’s now a bottom navigation bar with a floating upload button in the center. The Files page no longer uses a traditional table; instead, files are displayed as modern cards with encryption badges and a cleaner action menu that groups all available operations together. I also fixed some spacing issues on the login page caused by the fixed navbar.
Besides the UI, I spent some time improving the website from a technical perspective. I configured gzip compression, hid unnecessary server information, fixed some SEO issues like duplicated headings, and added both a robots.txt file and a sitemap.

Another important feature I implemented is the new Settings page. It now includes profile information, security settings, storage usage, and account management. I decided to keep the interface honest: only features that are actually supported by the backend are available, while future ones are clearly disabled. I also implemented permanent account deletion, both on the backend and frontend, making sure all related data is safely removed before the user is deleted.

I added a lot, I hope everything works as I expect.
See ya

0
0
5
Open comments for this post

10h 25m 26s logged

Hey guys, this week was also about making the CRM feel more complete. Alongside several new features, I also spent a good amount of time improving security and fixing one particularly deceptive bug.
First of all, I added a new global Calendar page that shows every record with a date in one monthly view.

Events, tasks, reminders and subscription renewals are all displayed together, each with its own color. Before this, the calendar only existed inside each record type, so there wasn’t a way to see everything happening at once. I also integrated Cal.com. The booking page can now be embedded directly inside the CRM, and when someone books a meeting, a webhook automatically creates an Event record. If the meeting is rescheduled, the existing record is updated instead of creating a duplicate, and if it’s cancelled, the event is removed.

To keep the integration secure, the webhook signature is verified using the raw request body instead of reserializing the JSON.

I spent some time looking at features from Pipedrive, HubSpot and Attio, then implemented a few that I really liked. The Kanban board now shows the total value of each column, making it easy to see how much every stage of the pipeline is worth. I also added rotting, which highlights cards that haven’t been updated for more than two weeks so forgotten leads are easier to spot.
Another big addition is public forms. Every record type can now expose a public form that can be shared with a link or embedded into any website. When someone submits it, a new record is created automatically and any related workflows are triggered. The feature also includes a honeypot for bots and per-IP rate limiting. Finally, I added a Trash Bin, allowing users to restore accidentally deleted records with a single click. I also added the ability to assign an owner directly from the record page.

Passwords now follow the same rules everywhere in the application:

  • at least 8 characters
  • one uppercase letter
  • one lowercase letter
  • one number
  • one special character.

The backend enforces the policy, while the frontend shows a live checklist as the user types.

I also added a Change Password page. When a password is changed, every other active session is logged out while the current one stays active.

At one point login stopped working and always returned “Invalid credentials”. It turned out the password wasn’t the problem at all, the backend was stuck in a crash loop.

A new database column was added as “not null” without a default value, so Hibernate couldn’t apply the change to an existing table. The application never finished starting, and the frontend showed a generic login error.

I fixed the database manually, added a default value to the migration, and made a note for the future: every new “not null” column should always have a default value.

After adding all these features, I went through another security pass. The rate limiter now also protects password changes and the Cal.com webhook. I also added a scheduled cleanup job that removes old expired sessions from the database.
Finally, I configured proper security headers, including a CSP. Public forms can still be embedded on external websites, while the rest of the CRM remains protected from being embedded elsewhere.

Stay tuned, cause I still have lots to do :)

0
0
2
Open comments for this post

3h 24m 29s logged

Okay guys, big news: I was finally able to get an SMTP server from a friend of mine, so now email verification and password recovery are working. I’m pretty satisfied; I really wanted this app to work as well as possible, and with email support, it feels even more complete.

Stay tuned, because it won’t be long before it’s ready.

0
0
2
Open comments for this post

44m 18s logged

Hey guys, I know this isn’t a proper devlog, but I wanted to show you this new tool I used yesterday, called graphify. Basically you take an AI, and you install graphify on it.
It will create this graph, that represents the project. I find it really useful for my actual process, reviewing. As you can see, I just need to start from the biggest Node, which is the “center” of the project, and then link every other Node.
The nice thing is that you can also ask questions, and the AI will respond also taking in consideration the graph, so the response will be more accurate. I strongly advice this tool for reviewing the code and improving the “style” of the code.
I hope you like it

0
0
9
Open comments for this post

4h 28m 43s logged

Hi guys
Lately I did much work. First of all, security audit fixes.

I bound internal ports to localhost; moved JWT secret to a real random value in .env; hardened rate limiting (to avoid spoofing); set file uploading limit to 40MB and switched uploads/downloads to streaming so files aren’t loaded whole into RAM.

Sharing rework (the main piece). Before, each user had one master DEK that encrypted all their files, and sharing sent that master DEK to the server in cleartext, so the server could decrypt shared files, and sharing one file handed over the key to every file. Now the master DEK only wraps other keys. Each file has its own random DEK (encrypting its content and name), stored wrapped by the master DEK.
Each user has an RSA keypair: the public key is stored in cleartext, the private key is wrapped by the master DEK (so password reset and recovery keep working without extra code). To share, the sender fetches the recipient’s public key and RSA-encrypts only that file’s DEK; the recipient decrypts it with their private key. The server never sees a key in cleartext, and the recipient gets access to only that one file. Public links work the same way, carrying the DEK for each file in the URL fragment (never sent to the server), with a revoke action.

To clean the code I also made an interfaces refactor. Moved all TypeScript interfaces into core/interfaces/, one per file (I), updated imports, removed the old model files.

I’m quite done, I still have to review some graphical aspects and improve some things in the code, but I think I’ll be done this week.

0
0
2
Open comments for this post

39m 5s logged

Okay guys, big problem. I realized I haven’t solved my problem with sharing files. I actually made things worse.

Now each user has one DEK that is used for encryption of all their files.
Two issues: the server is able to read the key (it decrypts shared files, thus E2EE is not provided), and when you give a person access to one file, you give the person access to all files.

The solution I need to implement: the master DEK will not be used for encrypting the files anymore, but will become a wrapping key, each file will have its own DEK which encrypts data in this particular file, and this DEK will be wrapped by the master DEK.

Each user should also have a key pair for RSA encryption: the public part of the key will be in cleartext, while the private part will be wrapped by the master DEK.

When a user shares a file, they encrypt only the DEK of this file with the recipient’s public RSA key, the recipient decrypts it with the private RSA key, and the server does not see any key in cleartext.

Wrapping the private key with the master DEK (not the password) means it’s recovered for free via the recovery key and survives password resets, so the existing login/recovery code stays untouched.

I hope to be able to fix this problem in reasonable time. I’ll stay in touch for further clarification and devlogs

P.S. in the screen you can see the DEK, proof for my thesis.

0
0
1
Open comments for this post

1h 34m 3s logged

Still improving the application. I want everything to be the best as possible. I fixed some minor bugs in fronted, mostly with the crypto service. I had some problems with the sharing of files, I realized I was also sharing the DEK of the user, which is really a problem since the receiver could, from that moment, decrypt every sender file.
After fixing it I improved some things in the backend, like the process of uploading and downloading files. Another important thing I fixed is the preview. The problem is that before I was opening the file directly in RAM, which, as I explained in some prev devlog, is a problem, since I have only 2 gb of ram. The important thing is that I was able to fix it, by opening it on disk.

0
0
1
Loading more…

Followers

Loading…